tags:

views:

582

answers:

4

I'm new to C. I have a book in front of me that explains C's "file scope", including sample code. But the code only declares and initializes a file scoped variable - it doesn't verify the variable's scope by, say, trying to access it in an illegal way. So! In the spirit of science, I constructed an experiment.

File bar.c:

static char fileScopedVariable[] = "asdf";

File foo.c:

#include <stdio.h>
#include "bar.c"

main()
    {
    printf("%s\n", fileScopedVariable);
    }

According to my book, and to Google, the call to printf() should fail - but it doesn't. foo.exe outputs the string "asdf" and terminates normally. I would very much like to use file scoping. What am I missing?

+6  A: 

You #included bar.c, which has the effect of causing the preprocessor to literally copy the contents of bar.c into foo.c before the compiler touches it.

Try getting rid of the include, but telling your compiler to compile both files (e.g. gcc foo.c bar.c) and watch it complain as you expect.

Edit: I suppose the primary confusion is between the compiler and the preprocessor. Language rules are enforced by the compiler. The preprocessor runs before the compiler, and acts on those commands prefixed by #. All the preprocessor does is manipulate plain text. It doesn't parse the code or try to interpret the meaning of the code in any way. The "#include" directive is very literal - it tells the preprocessor "insert the contents of this file here". This is why you normally only use #include on .h (header) files, and you only place function prototypes and extern variable declarations in header files. Otherwise, you will end up compiling the same functions, or defining the same variables, multiple times, which is not legal.

Tyler McHenry
Thank you, sir! I got it working.
Metaphile
+1  A: 

Remove the second include instruction. As it was said above...

Before compiling your code a compiler preprocesses it. In that stage it processes all the instructions starting with '#', like #include, #define and etc.

To see the result of that stage you can just run 'gcc -E ' (if you are using gcc).

dmitri
+3  A: 

This is caused by confusing terms. file scope in C does not refer to restrict linkage of an identifier to only one translation unit. It also doesn't mean that scope is limited to one physical file. Instead, file scope means that your identifier is global. The term file, here, refers to the text that results from processing all #include, #define and other pre-processor directives.

In general, scope is only a concept taking effect within one translation unit. When multiple compilations are involved, linkage starts to happen.

If you declare your file scope variable static, then it gives the variable internal linkage, which means that it isn't visible outside of that translation unit.

If you don't declare it static explicitly, or if you declare the file scope variable extern, then it is visible to other translation units: Those, if they declare a file-scope variable with the same identifier, will have that identifier link to that same variable.

In your case, the inclusion of bar.c into foo.c inserts the definition of fileScopeVariable into the translation unit being compiled. Thus, it's visible in that unit.

Johannes Schaub - litb
+1  A: 

Don't ever #include a .c file like you are doing there. The language allows it, but C coder's just don't do that, so you will confuse the heck out of people if you do it. Most likely including yourself.

"#include" means "Compiler, please go to that other file and tack it to the front of this one before you start compiling my code."

I once lost a whole day in total confusion because one of the vxWorks source files did this. I'm still POed at them over that.

T.E.D.
Thanks, I get it now. :-)
Metaphile