Why can I call a function from another file (with warning) but cannot use a variable from another file without declaring it?
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;
}
History, mostly. Early C was very lax (sloppy) in ways that continue the pain down to this day. The base K&R book was also vague in many points that the first ANSI standard firmed up when the committee aware of confusion points produced it. I consider using any extern without declaring it bad practice. Suspect this came about because languages like FORTRAN had no function declarations in it's early days and no external variables at all (not counting COMMON as externals). It can also depend on the warning level (if you are using gnu gcc try under -Wall).
C also has something called a "tentative definition" where a declaration without extern
can happen that may have contributed to the decisions.
Functions had default declarations (returns od integer, arguments as given) but variables would be a little more risky, given the way C freely converts data types. If you want to test this throw an int i;
into c.c and a float i = 12;
into d.c.