0

The C17 standard says that

If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.

Wouldn't this cause problems for extern-linkage identifiers? For example, if you had int i4; // tentative definition, external linkage in a header that was included by two files, without any definition anywhere. According to the way the clause is worded, it would seem that you would now effectively have a definition of int i4 = 0 in each translation unit, which would cause a multiple definition error. Nowhere does it mention that a variable defined in a different translation unit preventing this implied behavior.

I'm using msvc 2019 as the toolchain.

vbyzjnlehi
  • 307
  • 2
  • 15
  • 1
    Try `-fno-common` or equivalent, does that give you the behavior you expect? – zwol Nov 08 '21 at 00:38
  • Thanks. Looking through the documentation for `-fno-common`, this might explain the behavior. However, I'm on Windows and can't find the equivalent options. – vbyzjnlehi Nov 08 '21 at 00:48
  • 2
    Short answer to the way you have phrased it, regarding “which would cause a multiple definition error”: The C standard does not define the behavior when there are multiple definitions. In particular, it does not require there to be an error message, and it does not say that a linker may not coalesce the multiple definitions into one and successfully link the program. That is what GCC and Unix tools did by default until recently. Before GCC version 10, definitions resulting from tentative definitions were marked as “common,” and the linker would coalesce them. – Eric Postpischil Nov 08 '21 at 00:52
  • In version 10 and beyond, you can get the old behavior with `-fcommon`. In earlier versions, you can turn it off with `-fno-common`. – Eric Postpischil Nov 08 '21 at 00:53
  • 1
    Related: https://stackoverflow.com/a/17800382/315052 – jxh Nov 08 '21 at 00:54
  • @EricPostpischil Doesn't the standard explicitly state that "somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one" (section 6.5 item 5)? – vbyzjnlehi Nov 08 '21 at 01:56
  • @vbyzjnlehi: Sure, and the consequence for violating that rule is that the C standard does not define the behavior of the program or the C implementation. The standard neither requires nor prohibits an error message, and it neither requires nor prohibits coalescing the definitions and linking the program successfully. A “shall” rule in the standard does not mean **you** have to obey the rule. It just means that programs for which the standard defines the behavior shall obey the rule. For programs that do not obey it, other things are allowed to happen. GCC defined the behavior to coalesce. – Eric Postpischil Nov 08 '21 at 02:07
  • @vbyzjnlehi: That is something many people get wrong about the C standard. You are not required to write only “legal” or “valid” C programs. You can write programs that use all sorts of extensions provided by particular C implementations, such as this one that GCC and Unix tools provide. You are just stepping outside the area that the C standard defines and using behavior defined by the compiler or other tools. These programs can be *conforming* programs as the C standard defines it, although they are not *strictly conforming*. – Eric Postpischil Nov 08 '21 at 02:13
  • @zwol I compiled with mingw (`-fno-common` is the default) and it gave a multiple definition error, like I would have expected from reading the standard. Using `-fcommon` got rid of it. So combined with @EricPostpischil, what I was experiencing is nonstandard behavior of the msvc compiler. If my post wasn't (I believe too simplisticly) closed, I would have accepted your answers. – vbyzjnlehi Nov 08 '21 at 15:28

0 Answers0