tags:

views:

613

answers:

6

main.h

extern int array[100];

main.c

#include "test.h"

int array[100] = {0};

int main(void)
{
    /* do_stuff_with_array */ 
}

In the main.c module, the array is defined, and declared. Does the act of also having the extern statement included in the module, cause any problems?

I have always visualized the extern statement as a command to the linker to "look elsewhere for the actual named entity. It's not in here.

What am I missing?

Thanks.

Evil.

+8  A: 

yea, it's harmless. In fact, I would say that this is a pretty standard way to do what you want.

As you know, it just means that any .c file that includes main.h will also be able to see array and access it.

Evan Teran
+19  A: 

The correct interpretation of extern is that you tell something to the compiler. You tell the compiler that, despite not being present right now, the variable declared will somehow be found by the linker (typically in another object (file)). The linker will then be the lucky guy to find everything and put it together, whether you had some extern declarations or not.

To avoid exposure of names (variables, functions, ..) outside of a specific object (file), you would have to use static.

ypnos
Variables declared outside a function ARE global.
alex
Only if they are extern, otherwise they are local to the compilation unit they are in.
BigSandwich
yeah, but still they are global in C. whether they are static or not. however i don't see what that has to do with this answer. also in C++ variables are only global when they appear in :: and not in some user defined namespace.
Johannes Schaub - litb
These comments are verging on the unhelpful simply because "global" has no meaning here. Names have linkage: "none, internal, external".
Richard Corden
+1, if you don't want to expose something in a public header, yet need it in other modules, extern helps. Actually, everything in a public header (when linking against its object) is technically extern anyway. The keyword gives more flexibility.
Tim Post
For instance:extern sig_atomic_t sig_caught .. why expose that when all you want to do is put signal handlers in another module?
Tim Post
This is a great explanation. I never completely understood how `extern` works and now I do!
0A0D
The only thing missing from this answer is the answer to the question that was actually asked: "Does the act of also having the extern statement included in the module, cause any problems?" The answer: No.
Adrian McCarthy
+4  A: 

The extern is harmless and correct. You couldn't declare it in the header without extern.

As an extra, usually it is best practice to create a macro or a constant to hold the size of the array; in your code the actual size (100) appears twice in the source base. It would be cleaner to do it like this:

#define ARRAY_SIZE 100

extern int array[ARRAY_SIZE];

...

int array[ARRAY_SIZE] = { 0 };

But maybe you did not want to include this in the code snippet just for the sake of brevity, so please take no offense :)

antti.huima
+1  A: 

Also see How to correctly use the extern keyword in C.

aib
+4  A: 

Edit

In both C and C++, the presence of extern indicates that the first declaration is not a definition. Therefore, it just makes the name available in the current translation unit (anyone who includes the header) and indicates that the object referred to has external linkage - i.e. is available across all the translation units making up the program. It's not saying that the object is necessarily located in another translation unit - just that 'this line isn't the definition'.

End edit

In C, the extern is optional. Without it, the first declaration is a 'tentative definition'. If it were not for the later definition (which is unambiguously a definition because it has an initializer), this would be treated as a definition (C99 6.9.2). As it is, it's just a declaration and does not conflict.

In C++, the extern is not optional - without it, the first declaration is a definition (C++03 3.1) which conflicts with the second.

This difference is explicitly pointed out in Annex C of C++:

"Change: C++ does not have “tentative definitions” as in C

E.g., at file scope,

int i;
int i;

is valid in C, invalid in C++."

fizzer
A: 

From a compilation or execution point of view, it makes no difference.

However, it's potentially dangerous as it makes array[] available to any other file which #includes main.h, which could result in the contents of array[] being changed in another file.

So, if array[] will only ever be used in main.c, remove the line from main.h, and declare array[] as static in main.c.

If array[] will only be used in the main() function, declare it in there.

In other words, array[] should have its scope limited to the smallest possible.

Steve Melnikoff