An important idea in C is separate compilation: several programs can be compiled at different times and bound together. It can be done by linker
.
Although linkers don't understand C, they do understand machine language and memory layout, and it is up to each C compiler to translate C programs into terms that make sense to the linker.
The declaration
int a;
appearing outside of any function body is called a definition of the external object a
; it says that a
is an external integer variable and also allocates storage for it. Because it doesn't specify an initial value, the value is assume to be 0.
extern int a;
is not a definition of a
. It still says that a
is an external integer variable, but by including the external keyword, it explicitly says that the storage for a
is allocated somewhere else. From the linker's viewpoint, such a declaration is a reference to the external object a
but doesn't define it.
int a;
in both test1.c
and test2.c
. or
int a = 7;
in the test1.c
and
int a = 9;
in the test2.c
Here systems vary; But the last thing will rejected most system. The only way to avoid this trouble in all C implementations is to define each external variable exactly once.
static
modifier ANSI C
makes it easier to avoid conflicting with library names by listing all the functions that might possibly cause such conflicts. Any library function that calls another library function not on the list most do so by a "hidden name"
.
This allows a programmer to define a function called, say, read()
without worrying that getc()
will call that read()
instead of the system function.
꽤나 재미있는 내용.
The declaration
static int a;
means the same thing as
int a;
within a single source program file, but a
is hidden from other files.
Every C function has a list of parameters
, each of which is a variable that is intialized as part of calling the function.
A function is called by presenting it with a list of arguments
. There is no trouble with result types if every function is defined or declared before its first call in every file that calls it.
main() {
printf("%g\n", square(0.3));
}
it will give incorrect results when linked with square()
because main()
assumes that squre()
returns an int
when actually square()
returns a double
.
double squre();
Doing this relies on the caller to supply the right number of arguments of appropriate types. Appropriate does not necessarily mean eqaul: float
arguments are automatically converted to double
and short
or char
arguments are converted to int
.
extern int n;
long n;
This is not a valid c program but, many implementations will fail to detect this error.
There are many possibilities:
int
and long
values the same way internally.n
require different amount of storage. But, they happen to share storage in such way that the value assigned to one are valid for the other.n
share storage in such a way that assigning a value to one has the effect of apparently assigning a different value to the other.Thus the programmer is generally responsible for ensuring that all external definitions of a particular name have the same type in every object module. Moreover, "the same type" should be taken seriously.
/* In test1.c */
char filename[] = "/etc/passwd";
/* In test2.c */s
extern char *filename;
Although arrays and pointers are very similar in some contexts, they are not the same.
내가 생각하는 다른 이유:
sizeof
연산 결과가 다를 것이다.filename
은 수정 가능하다. 전자도 가능하나 Undefined Behavior
.One good way to avoid many problems of this sort is to adopt a simple rule: declare each external object in one place only.
header file
만들어 써라.
https://www.mythos-git.com/Cruzer-S/CTAP/-/tree/main/Chapter04
Exercise 2 는 꽤나 충격적이였다.
[Book] C Traps and Pitfalls (Andrew Koenig)
[Site] 네이버 영영, 영한사전