[hullo, I am c fan from poland, deep involved
in the spirit of c and structural coding,
From few years I am working and thinking about
some way of c language improvements. Sorry for
my weak english]
I want to say few words about some thing
I think it is wrong in c linking system
(as far as i know that bug is present in c
linking system at all)
On a 'compiler' (source) level, there is not
such thing as global function or variable -
the scope of symbol is limited to scope of
visibility of its declaration -
Yes, by definition. The compiler sees just one module
(one "compilation unit") at a time. It does not know what
other modules might link with it to form a complete program.
Sometimes the author of the code does not know what other
modules will be involved -- for instance, when you write a
library other people will use, you do not know what modules
they will combine with it.
but on linker level (as far as I heard
about it) linkers always try to link any
obj module with any other given module
- so it leads even to conflicts of symbols
not present on source level -it is obviously wrong
Not "obviously" to me. Suppose you compile one module
containing a function foo(), and a second module containing
a call to foo(). During compilation there is nothing to
connect the two appearances of the name `foo' -- the two
modules are compiled separately, one on Monday and one on
Tuesday, and the compiler never sees both `foo' uses at the
same time.
Then on Wednesday you combine the two compiled modules
into one program. In the combined program all the `foo' uses
must refer to the same thing. That is the job of the linker:
It collects all the `foo' uses in all the program's modules,
and makes all of them refer to the same function. Something
like this is a necessary step in any language that supports
separate compilation of modules.
Let's go a step further. Suppose Wednesday's program is
too slow, and you believe the foo() function is to blame. On
Thursday you think of a different way to implement foo(), but
you are not sure that it will be faster. So you write and
compile a third module that defines a foo() function, and now
you have three pairs of files:
foo.c, foo.o: the original foo() implementation
main.c, main.o: the module that calls foo()
foo_new.c, foo_new.o: the new foo() implementation
You can now link main.o with foo_new.o to get a program that
uses the new foo() version, even though main.o was compiled
before foo_new.c was written, before foo_new.c was imagined.
That is why the compiler cannot connect the `foo' uses in the
source files: It has no way to know what will connect to what.
Linker should not to try link everything with
everything but they should to be able to accept
some info about what module to link with
what other module (it would be obvious
improvement, easy to do - maybe evwn some
c linkers do things in such way now, i am
not sure)
C gives you some control over how the linker works, by
giving each identifier a "linkage." There are three kinds
of linkage:
- An identifier with "external linkage" is visible to the
linker. This is the default for variables and functions
declared at file scope in a module. Some identifiers
in other scopes can be given external linkage by using
the `extern' keyword.
- An identifier with "internal linkage" is invisible to
the linker. This is the linkage you get by using the
`static' keyword on a variable or function at file
scope. Different modules can use the same internal-
linkage identifier to refer to different things, and
the uses will not clash because the linker does not
see them.
- There are also identifiers with "no linkage," which are
things like function parameters, `auto' variables, typedef
names, macro names, and so on. The linker does not see
these, so different modules can use the same no-linkage
identifier for different things.
Perhaps some of your troubles might be solved if you used
the `static' keyword more often, so "module-private" identifiers
would have internal linkage instead of external linkage. For
example,
/* Private variable used only in this module */
static FILE *foo_stream;
/* Public variable visible to other modules */
int foo_count;
/* Private utility function used only in this module */
static void foo_helper_1(const char *greeting,
const char* person) {
fprintf(foo_stream, "%s, %s!\n", greeting, person);
}
/* Private utility function used only in this module */
static int foo_helper_2(void) {
++foo_count;
return foo_count & 7;
}
/* Public function other modules can call */
int foo(const char *person) {
foo_helper_1("Hello", person);
return foo_helper_2();
}
When the linker combines this module with others to make a program,
only the `foo_count' and `foo' identifiers are visible; they have
"external linkage." The identifiers `foo_stream', `foo_helper_1',
and `foo_helper_2' have "internal linkage" and will not conflict
with other modules' uses of the same names. The identifiers
`greeting' and `person' have "no linkage" and will not conflict
with the same names in other modules; indeed, the two appearances
of `person' in this module do not even conflict with each other.