Read-only outside translation unit

  • Thread starter Tomás Ó hÉilidhe
  • Start date
T

Tomás Ó hÉilidhe

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.
 
R

Richard

Tomás Ó hÉilidhe said:
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.
 
J

James Kuyper

Tomás Ó hÉilidhe said:
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.
 
T

Tomás Ó hÉilidhe

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 "*".
 
E

Eric Sosman

Tomás Ó hÉilidhe said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,586
Members
45,097
Latest member
RayE496148

Latest Threads

Top