// a.c
#include <stdio.h>
int main() {
printf("%d", sum());
}
// b.c
int sum() {
return 10;
}
I compile those two files with
gcc a.c b.c
normally, it works fine with an implicit declaration
warning and this warning disappears if I declare sum
in a.c
. I've read in another post that it is fine if I don't declare the function and if I call it properly, but it's not advised to do so and I should always declare what I use in each file, and this is fine and understandable.
What I don't understand is why there's a distinction between functions defined in another file and variables. Why can't I use a variable defined in another file in the same manner as above? I can also get it to run by declaring i
in the file where I use it, though.
// c.c
#include <stdio.h>
int main() {
printf("%d", i);
return ;
}
// d.c
int i = 12;
compiled with gcc c.c d.c
, produces the following error
c.c: In function ‘main’:
c.c:3:19: error: ‘i’ undeclared (first use in this function)
printf("%d", i);
^
c.c:3:19: note: each undeclared identifier is reported only once for each function it appears in
A function declaration tells the compiler about a function name and how to call the function. The actual body of the function can be defined separately. int max(int, int); Function declaration is required when you define a function in one source file and you call that function in another file.
The variable number is declared globally and may be accessed from other file when including its declaration with the “ extern ” prefix. However, the variable coefficient is only accessible from the file in which it is declared and only from that point on (it is not visible in function main .
First, the "implicit int" rule is long gone (since C99) and there's no case for not providing declarations in modern C (i.e. C99 and later).
However, why functions are OK with implicit declarations but not variables is because that's how it was initially defined in the pre-standard C (impplicit rules were valid in C89, too).
From Dennis Ritchie's C reference manual:
- Implicit declarations
It is not always necessary to specify both the storage class and the type of identifiers in a declaration. Sometimes the storage class is supplied by the context: in external definitions, and in declarations of formal parameters and structure members. In a declaration inside a function, if a storage class but no type is given, the identifier is assumed to be int; if a type but no storage class is indicated, the identifier is assumed to be auto. An exception to the latter rule is made for functions, since auto functions are meaningless (C being incapable of compiling code into the stack). If the type of an identifier is ‘‘function returning ...’’, it is implicitly declared to be extern. In an expression, an identifier followed by ( and not currently declared is contextually declared to be ‘‘function returning int’’.
Undefined identifiers not followed by ( are assumed to be labels which will be defined later in the function. (Since a label is not an lvalue, this accounts for the ‘‘Lvalue required’’ error message sometimes noticed when an undeclared identifier is used.) Naturally, appearance of an identifier as a label declares it as such.
(emphasis mine)
That means the following are OK:
// assumed to return int
func()
{
return 0;
}
// Type of 'some_var' defaults to int
void func2(some_var)
{
}
But this is not OK:
int func()
{
// Assumed to be labels; it's undeclared variable.
i;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With