Local scope, external linkage?

P

Peter Ammon

I would like to share a variable between two functions defined in two
separate source files; no other functions will need the global variable
so I'd prefer to not give it file scope. Thus, I want a variable with
local scope, external linkage, and static storage.

I believe I can do this for the file that does not define the variable
by declaring it inside a function. Can I also avoid giving it file
scope in the file that does define the variable?

/* File 1 */

void function1(void) {
/* How do I make myGlobal have static storage,
* and external linkage?
*/
int myGlobal;
}

/* File 2 */

void function2(void) {
/* This does what I think it does, right? */
extern int myGlobal;
}

Thanks for your help,
-Peter
 
J

Jeremy Yallop

Peter said:
I would like to share a variable between two functions defined in two
separate source files; no other functions will need the global variable
so I'd prefer to not give it file scope. Thus, I want a variable with
local scope, external linkage, and static storage.

You can't have one, I'm afraid.

If an identifier declared with external linkage is used in an
expression (other than as part of the operand of a sizeof operator
whose result is an integer constant), somewhere in the entire program
there shall be exactly one external definition for the identifier;
[C99 6.9]

External definitions always appear at file scope:

An external definition is an external declaration that is also a
definition of a function (other than an inline definition) or an
object.

translation-unit:
external-declaration
translation-unit external-declaration

About the closest you can get to what you want, I think, is to define
the variable in its own source file (or as the last declaration in one
of the source files in which it is used), and have block-scope
"extern" declarations (as in your example of function2()) in both the
functions that use the variable; this effectively limits scope to the
regions where the identifier is used. Since the same variable is
referenced in two separate translation units, the linkage must be the
maximum possible (i.e. "external").

Jeremy.
 
E

Eric Sosman

Peter said:
I would like to share a variable between two functions defined in two
separate source files; no other functions will need the global variable
so I'd prefer to not give it file scope. Thus, I want a variable with
local scope, external linkage, and static storage.

I believe I can do this for the file that does not define the variable
by declaring it inside a function. Can I also avoid giving it file
scope in the file that does define the variable?

/* File 1 */

void function1(void) {
/* How do I make myGlobal have static storage,
* and external linkage?
*/
int myGlobal;
}

/* File 2 */

void function2(void) {
/* This does what I think it does, right? */
extern int myGlobal;
}

C's linkage scheme is not fancy enough to do what
you desire. All identifiers with external linkage are
(potentially) visible to all parts of the program, and
there's no notion of a "package-private" linkage.

In the code you've shown, the identifier `myGlobal'
refers to two different objects:

- In function1(), it refers to an `auto' variable.
The identifier has no linkage, neither external
nor internal. You could change the storage class
by adding the `static' or `register' (or even
`typedef'!) keyword, but it wouldn't alter the
fact that this `myGlobal' has nothing at all to
do with any other `myGlobal' identifier that might
be lying around in your program.

- In function2(), `myGlobal' has external linkage.
When the various translation units are combined
into a program, this `myGlobal' and any others
that also have external linkage will be made to
refer to one object. Exactly one translation unit
must provide an actual definition of the object,
at file scope and without the `static' keyword --
and if that definition is a function or is a data
object that isn't `int', you've got trouble.

"You can't always get what you want." -- J&R
 
C

CBFalconer

Peter said:
I would like to share a variable between two functions defined in two
separate source files; no other functions will need the global variable
so I'd prefer to not give it file scope. Thus, I want a variable with
local scope, external linkage, and static storage.

I believe I can do this for the file that does not define the variable
by declaring it inside a function. Can I also avoid giving it file
scope in the file that does define the variable?

I think the closest you can come is:

/* File1.h */
typedef /* whatever */ foo;
foo *fooptrgetter(void);

/* File1.c */
#include "File1.h"
static foo foovalue;
foo *fooptrgetter(void) {return &foovalue)

and now any other file can access it by #include "File1.h" and
getting the pointer as needed.

If foo is a struct you can ensure readonly access by coding the
foogetter() function. Modifying foo would then be restricted to
functions in File1.c, and you can control their use by prototyping
them in a separate header file. An example of this mechanism
exposes the statistics from my hashlib package (see download
section of my site).
 
A

Alex Fraser

CBFalconer said:
Peter said:
I would like to share a variable between two functions defined in two
separate source files; no other functions will need the global variable
[snip]
I think the closest you can come is:

/* File1.h */
typedef /* whatever */ foo;
foo *fooptrgetter(void);

/* File1.c */
#include "File1.h"
static foo foovalue;
foo *fooptrgetter(void) {return &foovalue)

and now any other file can access it by #include "File1.h" and
getting the pointer as needed.

If foo is a struct you can ensure readonly access by coding the
foogetter() function.

Indeed, this scheme is largely pointless unless you do precisely that,
otherwise you might as well have the obvious:

/* File1.h */
typedef /* whatever */ foo;
extern foo foovalue;

/* File1.c */
#include "File1.h"
foo foovalue;

The only effective difference between this and the above is substituting one
external identifier for another.

Alex
 

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,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top