3

I have gone through following questions:

Above links describe that if we define global variable in one file and haven't specified extern keyword they will be accessible in another source file because of translation unit.

Now I have file1.c in that have defined following global variable and function:

int testVariable;

void testFunction()
{
    printf ("Value of testVariable %d \n", testVariable);
}

In file2.c have following code

void main()
{
    testVariable = 40;
    testFunction();
}

Now I am getting error: 'testVariable' undeclared (first use in this function) -- why?

Note: both files are used in same program using makefile.

As per my understanding both function and global variable have default external linkage. So function we can use directly by it's name in another file but variable can't why?

Can any one have idea?

EDIT:

From the below answer i get idea that like in case of function old compiler will guess and add an implicit declaration but in case of variable it can't. Also C99 removed implicit declaration but still I am getting warning in C99 mode like:

warning: implicit declaration of function ‘testFunction’.

Now have gone through below link:

implicit int and implicit declaration of functions with gcc compiler

It said that compiler take it as diagnostic purpose and not give error. So compiler can process forward.

But why in case of variable it can't process further? Even in case of function if compiler proceed and if actual definition not there then at linking time it will fail. So what's benefit to move forward??

Community
  • 1
  • 1
user2520119
  • 173
  • 11
  • If the compiler assumed that every undeclared variable was an `extern` object, you could never get warnings about missing declarations. Also, how would the compiler know what type the objects have? – EOF Jun 28 '16 at 11:41
  • @EOF then how compiler work in case of function? – user2520119 Jun 28 '16 at 11:44
  • In old C-standards, there is the concept of *implicit function declaration*. It's removed from newer standards and should be avoided. You might want to compile with a compiler-option to use a modern C-standard and warnings. – EOF Jun 28 '16 at 11:47
  • @EOF yes i know that we can avoid it by treating warning as error. but my question is why in case of variable it direct treat as error? – user2520119 Jun 28 '16 at 11:49
  • Of course you can access them. You just have to declare them in the files that want to access them. The standard way to do that is to put the external declarations in a header file (a `.h` file), then include that file where you want to use them. – Tom Karzes Jun 28 '16 at 12:02

2 Answers2

8

There are two things in play here: The first is that there is a difference between a definition and a declaration. The other thing is the concept of translation units.

A definition is what defines the variable, it's the actual place the variable exists, where the compiler reserves space for the variable.

A declaration is needed for the compiler to know that a symbol exists somewhere in the program. Without a declaration the compiler will not know that a symbol exists.

A translation unit is basically and very simplified the source file plus all its included header files. An object file is a single translation unit, and the linker takes all translation units to create the final program.

Now, a program can only have a single definition, for example a global variable may only exist in a single translation unit, or you will get multiple definition errors when linking. A declaration on the other hand can exist in any number of translation units, the compiler will use it to tell the linker that the translation references a definition in another (unknown at time of compilation) translation unit.

So what happens here is that you have a definition and a declaration in file1.c. This source file is used as input for one translation unit and the compiler generates a single object file for it, say file1.o. In the other source file, file2.c, there is no definition nor any declaration of the global variable testVariable, so the compiler doesn't know it exists and will give you an error for it. You need to declare it, for example by doing

extern int testVariable;  // This is a declaration of the variable

It's a little more complicated for the function, because in older versions of the C standard one didn't have to declare functions being used, the compiler would guess and add an implicit declaration. If the definition and the implicit declaration doesn't match it will lead to undefined behavior, which is why implicit function declarations was removed in the C99 standard. So you should really declare the function too:

void testFunction(void);  // Declare a function prototype

Note that the extern keyword is not needed here, because the compiler can automatically tell that it's a function prototype declaration.

The complete file2.c should then look like

extern int testVariable;  // This is a declaration of the variable

void testFunction(void);  // Declare a function prototype

void main()
{
    testVariable = 40;
    testFunction();
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 2
    Isn't the declaration of `int testVariable` in `file1.c` a *tentative* definition? – EOF Jun 28 '16 at 11:55
  • 2
    `void main()` should be `int main(void)`. But yes, that was wrong in the original code too! – Ian Abbott Jun 28 '16 at 12:14
  • if C99 removed implicit declaration of function then still i am getting warning `implicit declaration of function testFunction.`. on gcc compiler in c99 mode. it shouldn't be error???? – user2520119 Jun 29 '16 at 05:43
  • @IanAbbott Not necessarily, that's a myth. It is not as simple as dogmatically yelling "main should return int" in each and every case. For example if the OP's code is from an embedded system, it is perfectly fine and standard compliant. [See this for actual facts](http://stackoverflow.com/a/31263079/584518). – Lundin Jun 29 '16 at 08:06
  • 1
    @Lundin, yes true in a free-standing environment, but I think the default assumption should be that a hosted environment is being used, and `void main()` is one of those things from bad C programming books that keeps getting used incorrectly. – Ian Abbott Jun 29 '16 at 11:53
  • @IanAbbott Why would hosted environment be the default? Because that's the environment that _you_ use, or what? And if you read the dirty details of the linked post, you'll see that even for hosted systems, it is not clear if completely implementation-defined forms of main are allowed or not. If the standard itself isn't clear, it is rather arrogant to go around yelling "void main() is wrong". – Lundin Jun 29 '16 at 12:00
  • @Lundin, the use of standard library functions _suggests_ a hosted environment is in use in this case. – Ian Abbott Jun 29 '16 at 12:08
  • @IanAbbott No, any implementation may implement any standard library header. Freestanding implementations don't have to implement all headers if they don't want to, but nothing is stopping them from doing it. Unfortunately, stdio.h and other such mildly relevant headers are frequently implemented even for freestanding systems. You'll quite often see amateurs using printf even in resource-constrained 8 bit microcontroller systems. – Lundin Jun 29 '16 at 12:45
0

When compiler copes with file2.c it knows nothing about existence of testVariable and about its type. And as result it can't generate code to interact with such object. And purpose of line like

extern int testVariable;

is to let compiler to know that somewhere such object exists and has type of int. With functions we have no such problem because of next rule - if function is not defined - compiler assumes that it is defined somewhere like

int testFunction() { ... }

So you can pass any number of any arguments to it and try to obtain int return value. But if real function signature differs - you'll get an undefined behafiour at runtime. Because of this weakness such approach is considered as bad practice, and you should declare proper function prototype before any call to that func.

Sergio
  • 8,099
  • 2
  • 26
  • 52
  • So what is benefit of adding default external linkage to global variable although we need to write extern keyword to access in another file? – user2520119 Jun 28 '16 at 11:54
  • There is no benefits IMO. And default linkage has nothing to do with requirements to declare used top-level objects in each translation unit. – Sergio Jun 28 '16 at 12:00
  • @user2520119 There are no benefits. The language could have been defined in a way that made internal linkage the default when there are no other specifiers, but of course it wasn't defined like that. The usual practice is to put external declarations in a shared `.h` file `#include`d by all the `.c` files that refer to them. – Ian Abbott Jun 29 '16 at 12:25