Question Details

No question body available.

Tags

c gcc clang c89

Answers (3)

Accepted Answer Available
Accepted Answer
February 12, 2026 Score: 17 Rep: 234,720 Quality: Expert Completeness: 50%

Is this simply a non-compliance with the standard in these compilers, or am I missing something in the standard?

This conforms to the C 1990 standard because clause 4 says:

… A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any strictly conforming program…

-std=iso9899:1990 tells the compiler to use the 1990 C standard. It does not say to restrict programs to using only the core features of the standard. That is, it does not exclude extensions. The switch -pedantic will ask the compiler to diagnose many (but not all) extensions. With -pedantic, Clang and GCC will diagnose the use of long long and LL.

February 12, 2026 Score: 6 Rep: 158,871 Quality: High Completeness: 80%

Some related things about OP's post:

The LL in 9223372036854775806LL does not change the value of the constant. LL could have been omitted from constant in the example and still pose the issue of C89/90 allowing other long long related compiler extensions.


The code snippet uses 3 C89 extensions:

  • LL as an integer constant suffix noted by OP.

  • long long as a type as wide/wider than long.

  • Prefix "ll" in "%lld" to indicate a format for long long.


Constant 9223372036854775806LL and 9223372036854775806 both have the value of 9,223,372,036,854,775,806.

On 32-bit int, 64-bit long systems, 9223372036854775806 becomes a long.

Back in C89 days, 9223372036854775806 was more likely on a 32-bit int/unsigned, 32-bit long system and so was out-of-range. With compiler extensions, 9223372036854775806 could then be a long long, with or without the LL.

February 13, 2026 Score: 2 Rep: 220,974 Quality: Medium Completeness: 100%

First here's an explanation of some terms that the gcc folks follow. In C there are the formal terms strictly conforming program and conforming program.

A strictly conforming program does not contain any forms of undefined/unspecified/implementation-defined behavior, meaning it is a mostly theoretical utopia, barely possible to achieve in practice.

A conforming program is one that may have implementation-defined behavior and extensions but none of them break a strictly conforming program.

Programs that are neither of the above are informally called "non-conforming".

A compiler that accepts a strictly conforming program is a "conforming implementation". A compiler is non-conforming if it refuses to compile a strictly conforming program, or if it silently lets through a non-conforming program.

Any form of non-conformance is reported by the compiler in the form of a diagnostic message. Error or warning does not matter, as long as the message was reported - see What must a C compiler do when it finds an error?


Now as for gcc-like compiler options, they are strange and unintuitive, in this way:

  • -std=gnuxx or no -std option at all means: throw in a huge amount of non-standard extensions and feel free to break strict conformance. The version "xx" may enable extra features that came with a certain version of the equivalent C standard.
  • -std=cxx means "throw in a huge amount of non-standard extensions, but when you do, do not break strictly conforming programs according to version xx of standard C". It does not mean compile and expect strict conformance to a certain version of the standard.
  • -std=cxx -pedantic means "compile with conformance to version xx of standard C and also give a diagnostic message in case of non-standard extensions". This does not necessarily result in a diagnostic message in case of implementation-defined behavior though, but it is the closest thing gcc-like compilers have to a conforming mode.
  • ansi means exactly the same thing as -std=c89. It does not mean compile for strict ANSI/ISO compliance.
  • -Wall means "a fistful of warnings". It does not mean enable all warnings (doh, what made you think that...).
  • -Wextra means "a few warnings more". Again, it does not not mean enable all warnings.

Examples:

With no -std option or std=gnu89, long long and LL are language extensions. Support for %lld is an implementation-defined library extension. Adding -std=c89 or similar does not change any of that, none of the extensions break a strictly conforming program. -std=c89 -pedantic gives warnings for all of the extensions.

Now lets say that we rewrite your program with one single change: replace the variable name a with the variable name bool, which is not yet a keyword by the time of C89. But it was a gnu non-standard extension, so in gnu89 mode, I now get compiler errors. Meaning that the compiler refuses a strictly conforming C89 program, where bool is a valid name for an identifier. Swapping to -std=c89 removes the error. Adding -pedantic brings back all the previous warnings and still accepts bool as an identifier.

Similarly if I add #include and char str = strdup("");, that compiles just fine with gnu89 because strdup is a POSIX extension. If I switch to -std=c89 then all the POSIX functions that break C conformance gets stripped away from standard headers, and then suddenly there is no prototype for strdup. After which I get a super-confusing warning "initialization of 'char ' from 'int' makes pointer from integer without a cast". This is because of C89 implicit int which treats unknown functions as if they have return type int. And suddenly the program will go bananas because of that.

Another example is const int x = 1; int y = x; declared at file scope outside any function. Here x is an implementation-defined constant expression.