Reputation: 13
I have 2 files:
a.c
b.c
a.c:
#include <stdio.h>
#include "b.c"
int main()
{
printf("%s", B_VAR);
return 0;
}
b.c:
static char B_VAR[] = "Hello world!\n";
Compile and run:
jonathan:~/code/staticDemo$ gcc a.c -o test
jonathan:~/code/staticDemo$ ./test
Hello world!
I was under the impression that static would make B_VAR
limitted to b.c
only, yet this seems to work.
Upvotes: 0
Views: 151
Reputation: 139
It is true that the static
keyword makes variables only visible to a single C file. However, in a.c
you are including b.c
meaning that it is not compiled and linked with a.c, but instead copied into a.c
.
The C preprocessor copies one file to another when including, and the preprocessor is executed before the file is compiled.
So this is the effective code to be compiled (generated with GCC using the -e
flag, and excluding the <stdio.h>
definitions):
# 2 "a.c" 2
# 1 "./b.c" 1
static char B_VAR[] = "Hello world!\n";
# 3 "a.c" 2
int main()
{
printf("%s", B_VAR);
return 0;
}
And this means that B_VAR
is accessible in a.c
because it really is in a.c
.
If you instead compiled each separately and linked them together for the final executable, B_VAR
would not be accessible.
Example (-c
means to only preprocess and compile, but don't link):
gcc -c a.c -o a.o
(GCC fails with use of undeclared identifier 'B_VAR'
)
gcc -c b.c -o b.o
gcc a.o b.o -o test
./test
Hope this helped.
Upvotes: 1
Reputation: 223689
The files a.c and b.c are not compiled independently of each other. You're including b.c inside of a.c. So what the compiler sees after preprocessing for a.c looks like this:
// contents of stdio.h
static char B_VAR[] = "Hello world!\n";
int main()
{
printf("%s", B_VAR);
return 0;
}
So what static
actually does it make a variable / function local to the compliation unit in which is resides which may consist of one or more source files that are included together.
Had you removed the include and compiled the two files separately, then you would see an error.
Upvotes: 0
Reputation: 72271
The static
keyword as used there makes a variable local to a "translation unit", not a file. An #include
directive pulls all the contents of the named file into the current translation unit. So yes, B_VAR
is accessible.
To create a program using multiple translation units, you would skip the #include "b.c"
and instead give both source files to the compiler driver:
$ gcc a.c b.c -o test
Normal practice is to never #include
a source file, only header files. When a project gets more complicated, including a source file via multiple other files will cause multiple definition errors.
Upvotes: 0