Recently, I found out there are some cases that will absolutely violate the ODR of C++ but will be compiled OK in C compiler.
For example, this wierd scenario (with me):
Source 1
int var_global=-3;
Source 2
#include <stdio.h>
#include <conio.h>
unsigned int var_global;
int main() {
printf("%d \n",var_global);
getch();
return 0;
}
I have the printed result is -3
(even though in Source 2 var_global
is unsigned
) and there is no error about the redefined of var_global
.
I knew that C have different rules with C++ but I don't think it's so different like that.
I have google and read a lot of results but there is no official result like this of C++.
So question is:
Does C have One Definition Rule like C++ ?
and:
What is it called officially?
I need it to compare with the rule of C++ so that I can understand both languages deeper.
p/s: I used Visual Studio 2010 for compiling the code above.
I think what you're looking for is chapter §6.2.7 from the C11
standard, Compatible type and composite type, (emphasis mine)
All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.
and related to compatible type,
Two types have compatible type if their types are the same.
In your case, int
and unsigned int
are not compatible types. Hence undefined behavior.
Just to add a bit of clarity, in your source 2, unsigned int var_global;
is a declaration, and it does not match the other declatation (and definition), so, this is UB.
That said, a statement like
printf("%d \n",var_global);
will always consider the argument to %d
to be of type int
. In case the type and the format specifier does not match, you'll again invoke undefined behavior.
EDIT:
After the edit, the answer is, use -fno-common
to get the desired error. (missing extern
is what you're bothered with, I believe).
Quoting from online GCC manual,
-fno-common
In C code, controls the placement of uninitialized global variables. Unix C compilers have traditionally permitted multiple definitions of such variables in different compilation units by placing the variables in a common block. This is the behavior specified by -fcommon, and is the default for GCC on most targets. On the other hand, this behavior is not required by ISO C, and on some targets may carry a speed or code size penalty on variable references. The -fno-common option specifies that the compiler should place uninitialized global variables in the data section of the object file, rather than generating them as common blocks. This has the effect that if the same variable is declared (without
extern
) in two different compilations, you get a multiple-definition error when you link them. In this case, you must compile with -fcommon instead. Compiling with -fno-common is useful on targets for which it provides better performance, or if you wish to verify that the program will work on other systems that always treat uninitialized variable declarations this way.
I don't know of any mention of the wordings "one definition rule" in the C standard, but along the line, you can look into annex §J.5.11, Multiple external definitions,
There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword
extern
; if the definitions disagree, or more than one is initialized, the behavior is undefined.
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