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??

5
  • 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? Commented Jun 28, 2016 at 11:41
  • @EOF then how compiler work in case of function? Commented Jun 28, 2016 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. Commented Jun 28, 2016 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? Commented Jun 28, 2016 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. Commented Jun 28, 2016 at 12:02

2 Answers 2

7

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();
}
Sign up to request clarification or add additional context in comments.

8 Comments

Isn't the declaration of int testVariable in file1.c a tentative definition?
void main() should be int main(void). But yes, that was wrong in the original code too!
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????
@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.
@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.
|
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.

3 Comments

So what is benefit of adding default external linkage to global variable although we need to write extern keyword to access in another file?
There is no benefits IMO. And default linkage has nothing to do with requirements to declare used top-level objects in each translation unit.
@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 #included by all the .c files that refer to them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.