First of all, please help me to find a better title which will describe the situation more accurately. I created the following simplified version of a problem I stumbled on when debugging real-world (embedded) code.
Consider the following code of file t1.c
:
#include <stdio.h>
int A;
void f() { printf("%d\n", A); }
extern void g();
void main(void)
{
g(); A=1; g();
A++;
f();
}
and the code of t2.c
:
#include <stdio.h>
double A;
void g()
{
A += 1.0;
printf("%f\n", A);
}
Now compiling and running the code like this:
gcc -Wall t1.c t2.c -o t && ./t
gives
1.000000
2.000000
1
Note that both files contain a global variable call A
which has a different type. I expected a link error because the symbol A exists multiple times.
I actually get a link warning (object size changes in different .o) when I initialize one of the two variables, an error (multiple definitions) when I initialize both of them.
I tried this with gcc 4.7 and 4.4.
Is this expected behavior? If so, is there something I can do to instruct the toolchain (gcc-based) to warn about it?
Is this a bug?
If a global and a local variable with the same name are in scope, which means accessible, at the same time, your code can access only the local variable.
In computing, an uninitialized variable is a variable that is declared but is not set to a definite known value before it is used. It will have some value, but not a predictable one. As such, it is a programming error and a common source of bugs in software.
It should give error as we cannot declare same name variables in same storage class.
There is no problem if it is inside a function as it is a local variable. If it is a global declaration, it depends on the linker. You can get a link error (or if you use options to direct it to do so). Otherwise they will be consolidated into one location as if you had declared them external.
Yes, compile with -fno-common
option to get the linker error:
$ gcc -Wall -fno-common -c t1.c
$ gcc -Wall -fno-common -c t2.c
$ gcc t1.o t2.o -o t
t2.o:t2.c:(.bss+0x0): multiple definition of `_A'
t1.o:t1.c:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status
$
If you want to compile this in one line you can also pass the --warn-common
to the linker (here with --fatal-warnings
to have an error instead of a warning):
$ gcc -Wl,--fatal-warnings,--warn-common -Wall t1.c t2.c -o t
/tmp/cc1xQo79.o: warning: common of `_A' overriding smaller common
/tmp/ccLnhxoe.o: warning: smaller common is here
collect2: error: ld returned 1 exit status
$
By default gcc
performs various optimizations of C undefined behaviors as an extension. C allows any implementation to stop translation in presence of such a program, so except if you have excellent reasons to do it, you should avoid it.
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