Read-only outside translation unit

Discussion in 'C Programming' started by Tomás Ó hÉilidhe, Dec 8, 2007.

  1. I have a translation unit which defines a global object:

    BEGIN "yellow.c"

    int i = 7;

    END

    I want this object to be accessible from other translation units, so I give
    it external linkage. However I want it to be read-only in other translation
    units. I didn't think it was too far-fetch to simply declare it as follows
    in a header file:

    BEGIN "yellow.h"

    extern int const i;

    END

    Is this definitely not supported by C89? I realise I could write a function
    which would return the variable's value, but I thought a solution like
    above would be neater.

    --
    Tomás Ó hÉilidhe
     
    Tomás Ó hÉilidhe, Dec 8, 2007
    #1
    1. Advertising

  2. Tomás Ó hÉilidhe

    Richard Guest

    "Tomás Ó hÉilidhe" <> writes:

    > I have a translation unit which defines a global object:
    >
    > BEGIN "yellow.c"
    >
    > int i = 7;
    >
    > END
    >
    > I want this object to be accessible from other translation units, so I give
    > it external linkage. However I want it to be read-only in other translation
    > units. I didn't think it was too far-fetch to simply declare it as follows
    > in a header file:
    >
    > BEGIN "yellow.h"
    >
    > extern int const i;
    >
    > END
    >
    > Is this definitely not supported by C89? I realise I could write a function
    > which would return the variable's value, but I thought a solution like
    > above would be neater.


    I would say you're better off using get/set - with the set not exported
    to other modules. Don't export the variable using the header - just give
    access via your "get" routine. Much cleaner and safer IMO - more
    apparent to the calling code which is getting access to the read only
    (from outside its home module) variable too.
     
    Richard, Dec 8, 2007
    #2
    1. Advertising

  3. Tomás Ó hÉilidhe

    James Kuyper Guest

    Tomás Ó hÉilidhe wrote:
    > I have a translation unit which defines a global object:
    >
    > BEGIN "yellow.c"
    >
    > int i = 7;
    >
    > END
    >
    > I want this object to be accessible from other translation units, so I give
    > it external linkage. However I want it to be read-only in other translation
    > units. I didn't think it was too far-fetch to simply declare it as follows
    > in a header file:
    >
    > BEGIN "yellow.h"
    >
    > extern int const i;
    >
    > END
    >
    > Is this definitely not supported by C89? I realise I could write a function
    > which would return the variable's value, but I thought a solution like
    > above would be neater.


    If it's not too inconvenient, you can use indirection to achieve the
    desired result:


    "yellow.h":

    extern const int * const pi;


    "yellow.c":

    #include "yellow.h"
    static int i=7;
    const int * const pi = &i;

    Note: you should always #include a header file in the translation unit
    that defines one of the objects or functions declared in the header.
    This isn't needed for correct compilation, so people often thing it's
    not useful. However, it helps ensure that you will be warned if your
    header's declaration is inconsistent with the definition.
     
    James Kuyper, Dec 8, 2007
    #3
  4. James Kuyper <> wrote in
    news:Y2x6j.1026$bW.251@trnddc07:

    > If it's not too inconvenient, you can use indirection to achieve the
    > desired result:
    >
    >
    > "yellow.h":
    >
    > extern const int * const pi;
    >
    >
    > "yellow.c":
    >
    > #include "yellow.h"
    > static int i=7;
    > const int * const pi = &i;



    Or maybe:

    "yellow.h":

    extern int const *const pi;
    #define i (*pi)


    ( ...and yes I *do* realise there'll be trouble if there's any variables
    called "i" within functions.)

    I've decided to just have the object non-const throughout all the
    translation units... I just have to be sure I don't do something stupid
    like write "*=" instead of "*".


    --
    Tomás Ó hÉilidhe
     
    Tomás Ó hÉilidhe, Dec 8, 2007
    #4
  5. Tomás Ó hÉilidhe

    Eric Sosman Guest

    Tomás Ó hÉilidhe wrote:
    > I have a translation unit which defines a global object:
    >
    > BEGIN "yellow.c"
    >
    > int i = 7;
    >
    > END
    >
    > I want this object to be accessible from other translation units, so I give
    > it external linkage. However I want it to be read-only in other translation
    > units. I didn't think it was too far-fetch to simply declare it as follows
    > in a header file:
    >
    > BEGIN "yellow.h"
    >
    > extern int const i;
    >
    > END
    >
    > Is this definitely not supported by C89? I realise I could write a function
    > which would return the variable's value, but I thought a solution like
    > above would be neater.


    You'll probably get away with it, but I see two problems
    (others may see more):

    - You'll be unable to #include "yellow.h" in the compilation
    of yellow.c, because the const and non-const declarations
    conflict. This isn't fatal, but it means the compiler
    never gets a chance to detect other mismatches between
    the declarations in the header and the definitions in the
    .c file -- change `int' to `long' in just one place, for
    example, and the compiler won't be able to warn you.

    - Nothing prevents an "outsider" from writing his own
    `extern int i;' declaration or from setting up a pointer
    with `int *pi = (int*)&i;', and mucking with the value
    of `i' to his heart's content. This, too, is non-fatal
    under the assumption of "cooperative" outsiders, but the
    protection given by `const' is merely advisory if the
    actual object has external linkage and isn't really `const'.

    For greater cleanliness and greater protection, if you need
    either, use an accessor function. If you don't like the syntax,
    you can disguise it with a macro:

    /* yellow.c */
    static int i;
    int geti(void) { return i; }

    /* yellow.h */
    int geti(void);
    #define i ( geti() )

    .... although indiscriminate use of this tactic can make garbage
    out of otherwise clean code.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Dec 8, 2007
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. keithb
    Replies:
    2
    Views:
    8,076
    keithb
    Jun 7, 2006
  2. Chris Croughton

    Is an empty translation unit valid?

    Chris Croughton, Jun 28, 2005, in forum: C Programming
    Replies:
    4
    Views:
    358
    Kenny McCormack
    Jul 3, 2005
  3. aaragon
    Replies:
    4
    Views:
    311
    aaragon
    Nov 26, 2007
  4. Mark
    Replies:
    5
    Views:
    359
    James Kuyper
    Sep 28, 2011
  5. Tim McDaniel
    Replies:
    0
    Views:
    103
    Tim McDaniel
    Apr 9, 2009
Loading...

Share This Page