Globals and Exports

B

Bartc

I noticed that in C, functions in any module are automatically exported. So
that it's not possible to use the same function name in two modules (ie.
source files).

Now that I know that, I get work around it; but is there a way to avoid the
problem (short of lots of renaming)?

More seriously, variables declared at file scope also seem to be
automatically exported. But in this case, the compiler/linker doesn't warn
me that the same name is being used in two or more modules. (Is this what
the fuss is about with 'global variables'?)

Is there any way I can fix this? (Like some keyword that will render a
variable local to a module.)

-- Bartc
 
A

Antoninus Twink

I noticed that in C, functions in any module are automatically exported. So
that it's not possible to use the same function name in two modules (ie.
source files).

Now that I know that, I get work around it; but is there a way to avoid the
problem (short of lots of renaming)?

Check out your compiler's options. For example, gcc has quite a
sophisticated visibility model: in the simplest case, you can use
__attribute ((visibility("hidden"))) as a qualifier, or compile with
-fvisibility=hidden.
More seriously, variables declared at file scope also seem to be
automatically exported. But in this case, the compiler/linker doesn't warn
me that the same name is being used in two or more modules. (Is this what
the fuss is about with 'global variables'?)

Is there any way I can fix this? (Like some keyword that will render a
variable local to a module.)

static.
 
F

Flash Gordon

Bartc wrote, On 05/05/08 10:53:
I noticed that in C, functions in any module are automatically exported. So
that it's not possible to use the same function name in two modules (ie.
source files).

Your C text book should have told you this. If not you need to reread it
and/or replace it.
Now that I know that, I get work around it; but is there a way to avoid the
problem (short of lots of renaming)?

More seriously, variables declared at file scope also seem to be
automatically exported.
Yes.

But in this case, the compiler/linker doesn't warn
me that the same name is being used in two or more modules.

It is not required to. Some can be made to however, so you should read
the documentation for your implementation.
(Is this what
the fuss is about with 'global variables'?)

High coupling making it hard to understand programs. You have to read
every function (or you search facilities on the entire code base) to
find out when and how the variables are changed and where they are used,
then you find you have a problem because you cannot change one piece of
code without breaking lots more.

The larger the project the larger the problem.
Is there any way I can fix this? (Like some keyword that will render a
variable local to a module.)

Look up the many uses of static in your text book.
 
F

Flash Gordon

Antoninus Twink wrote, On 05/05/08 11:12:
Check out your compiler's options. For example, gcc has quite a
sophisticated visibility model: in the simplest case, you can use
__attribute ((visibility("hidden"))) as a qualifier, or compile with
-fvisibility=hidden.

So what is wrong with static? Why suggest a non-standard extension when
a feature the language has had in all implementations for years is
sufficient.

After all, you know about it.
 
A

Antoninus Twink

Antoninus Twink wrote, On 05/05/08 11:12:

So what is wrong with static? Why suggest a non-standard extension when
a feature the language has had in all implementations for years is
sufficient.

Because they do different things. If you're making a shared library,
then you might want to have variables and functions that are globally
visible within your library, but don't pollute the namespace for users
of your library. Gcc's __attributes can achieve that.

Without extensions, you have only two choices: either make a variable
static, and so visible only within a single translation unit, or else
make it globally visible everywhere. Compiler extensions can provide
finer-grained visibility control, which seems to be what the OP had in
mind: when you link your shared library, all uses of a symbol throughout
the library files are resolved, but that symbol isn't put into the table
of externally-visible symbols in your .so file.
 
F

Flash Gordon

Antoninus Twink wrote, On 05/05/08 14:00:
Because they do different things. If you're making a shared library,

<snip>

Which is not what the OP was asking about. The OP make clear in what he
posted that by modules he meant source files. This is actually quoted by
you immediately before your response.
 
T

Tomás Ó hÉilidhe

I noticed that in C, functions in any module are automatically exported. So
that it's not possible to use the same function name in two modules (ie.
source files).


You can't have two functions with the same name, correct. (I changed
your wording because it could have meant that you can't call a
function from another translation unit).

Now that I know that, I get work around it; but is there a way to avoid the
problem (short of lots of renaming)?

More seriously, variables declared at file scope also seem to be
automatically exported.


The linkage of a function or object can be either "extern" or
"static". You are right in thinking that the default is "extern", but
beware of the exception to the rule: if the object is const, then the
default becomes "static". I.e. the following two global object
definitions are the same:

int const i = 5;

static int const i = 5;

But in this case, the compiler/linker doesn't warn
me that the same name is being used in two or more modules. (Is this what
the fuss is about with 'global variables'?)

Is there any way I can fix this? (Like some keyword that will render a
variable local to a module.)


Instead of having:

int GetNumber(void) { return 5; }

you have:

static int GetNumber(void) { return 5; }

The difference this makes is that when the compiler produces an object
file for the translation unit in question, it doesn't list "GetNumber"
in the object file's list of functions. Therefore, when the linker
links different object files together, it never sees the "GetNumber".
The net effect of this is:

1) You can have a function with the same name in a different
translation unit.
2) You cannot call the function from a different translation unit.

There is another kind of visiblity problem you might encounter. Let's
say you're writing a program that deals with Ethernet and also with
USB. For this, you might be using two different libraries, one for the
Ethernet and one for the USB. The Ethernet library might have a
function called "CheckConnection", and the USB library might have a
function by exactly the same name.

Since we want both these functions to be exported from their
respective object files, we have a problem.

In C++, the introduced the concept of "namespaces". Basically you'd
have:

USB::CheckConnection();
Ethernet::CheckConnection();

In C though, I think the best you can do is:

USB_CheckConnection();
Ethernet_CheckConnection();

That is to say, you'd have to actually change the function's name,
perhaps by prepending the library name to it.
 
T

Tomás Ó hÉilidhe

You are right in thinking that the default is "extern", but
beware of the exception to the rule: if the object is const, then the
default becomes "static". I.e. the following two global object
definitions are the same:

    int const i = 5;

    static int const i = 5;


Sorry sorry sorry! Don't listen to me! I had a nagging in my head as I
was writing that that I might be confusing C with C++, so I opened up
notepad to try it out, and lo and behold I should have investigated my
nagging feeling before I posted.

The default for const global objects is in fact "extern" in C.
 
M

Martin Ambuhl

Bartc said:
I noticed that in C, functions in any module are automatically exported. So
that it's not possible to use the same function name in two modules (ie.
source files).

Look up the keyword "static". You will find that your assertion is false.
Now that I know that, I get work around it; but is there a way to avoid the
problem (short of lots of renaming)?

Look up the keyword "static".
More seriously, variables declared at file scope also seem to be
automatically exported. But in this case, the compiler/linker doesn't warn
me that the same name is being used in two or more modules. (Is this what
the fuss is about with 'global variables'?)

Look up the keyword "static".
Is there any way I can fix this? (Like some keyword that will render a
variable local to a module.)

Look up the keyword "static".
 
J

John Bode

I noticed that in C, functions in any module are automatically exported. So
that it's not possible to use the same function name in two modules (ie.
source files).

Now that I know that, I get work around it; but is there a way to avoid the
problem (short of lots of renaming)?

Declare the items you want to keep "private" static:

/** myfile.c */

/**
* The following variable and function cannot be
* referred to by name outside of myfile.c; however,
* they can still be referred to using pointers returned
* from other functions within the file.
*/
static int x;
static void foo() {...}
More seriously, variables declared at file scope also seem to be
automatically exported. But in this case, the compiler/linker doesn't warn
me that the same name is being used in two or more modules. (Is this what
the fuss is about with 'global variables'?)

The compiler will attempt to resolve multiple declarations of the same
variable into a single entity according to one of several models. The
key thing is that only one declaration can be a *defining*
declaration, and all the rest are *referencing* declarations. There
are several models by which the compiler determines which is a
defining vs. referencing declaration. Anything with an initializer is
considered a defining declaration; if you had two declarations with
initializers, and the initializers were different values, you would
get a diagnostic.

The problem with globals is that they promote tight coupling between
modules, discouraging code reuse. For example, if you had a sorting
routine that relied on the presence of a global variable to indicate
the array size, you could not reuse that routine in a program that did
not define that global.
Is there any way I can fix this? (Like some keyword that will render a
variable local to a module.)

-- Bartc

Like I said, use the static qualifier for each item you don't want
exported. Remember that doing so only prevents other modules from
referring to those entities by name; there's nothing preventing you
from writing a function to return a pointer to a static item, thus
making it available to other modules by reference. But it at least
allows you to reuse names.
 
N

Nick Keighley

Check out your compiler's options. For example, gcc has quite a
sophisticated visibility model: in the simplest case, you can use
__attribute ((visibility("hidden"))) as a qualifier, or compile with
-fvisibility=hidden.

don't use compiler specific extensions when you don't have to.
Use static to keep things at file scope.
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top