Jonathan
Jonathan

Reputation: 13

Why can I access a static variable in another file?

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

Answers (3)

reeeee
reeeee

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

dbush
dbush

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

aschepler
aschepler

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

Related Questions