首页 > 解决方案 > Shall a #pragma leading to nonstandard behavior cause __STDC__ macro not to be defined to 1?

问题描述

Simple question: shall a #pragma leading to nonstandard behavior cause __STDC__ macro not to be defined to 1? (Does the C standard explicitly prescribes that? If yes, then in which section? If no, then why?) Reason of the question: see below.

Sample code (t28.c):

#pragma warning( disable : 34 )
typedef int T[];

int main()
{
    int rc = sizeof(T);
#if __STDC__ == 1
    rc = 0;
#else
    rc = 1;
#endif
    return rc;
}

Invocation: cl t28.c /std:c11 /Za && t28 ; echo $?

Expected result: 1

Actual result: 0

Compiler version:

cl
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29913 for x64

Note: C11 (6.5.3.4 The sizeof and _Alignof operators) (emphasis added):

The sizeof operator shall not be applied to an expression that has function type or an incomplete type, ...

Here we see that #pragma leads to nonstandard behavior: "shall requirement" is violated, diagnostic message is not generated, compiler's backend is called, .exe is produced and successfully executed. However, this nonstandard behavior does not cause __STDC__ macro not to be defined to 1.

Reason of the question: tests. One test, similar to t28.c is failing because it expects return code 1 (__STDC__ is not defined to 1). Which part of the system contains the bug: test or compiler (or both)?

标签: cvisual-c++language-lawyerc11standards-compliance

解决方案


Here we see that #pragma leads to nonstandard behavior: "shall requirement" is violated, diagnostic message is not generated, compiler's backend is called, .exe is produced and successfully executed. However, this nonstandard behavior does not cause __STDC__ macro not to be defined to 1.

First, the __STDC__ macro is not intended to be a mechanism for reporting “something happened during this compilation that resulted in nonstandard behavior.” It is not dynamic (changing) in that way. The desire for __STDC__ is simply for it to report that the C implementation is conforming. (It is only a desire because the C standard can require that conforming implementations define __STDC__ to be 1 but has no control over what nonconforming implementations define it to be.) If an implementation is conforming, __STDC__ will always be 1 regardless of what happens in any particular compilation.

(Note that one compiler may include multiple C implementations selected by various command-line switches, such as requesting different sizes for various types, enabling or disabling conforming extensions, enabling non-conforming variations from the C standard, and so on. Some combinations of switches may result in __STDC__ being defined to be 1 while others do not.)

Second, the #pragma warning( disable : 34 ) does not leading to nonstandard behavior. Per C 2018 6.10.6 1, this directive “causes the implementation to behave in an implementation-defined manner. The behavior might cause translation to fail or cause the translator or the resulting program to behave in [an otherwise] non-conforming manner.” So, supposing the pragma is documented by the implementation to suppress the warning about violation of the constraint in 6.5.3.4 1 about the sizeof operator, then this is permitted by the C standard. This rule in 6.10.6 1 overrides the constraint in 6.5.3.4 1. The behavior is permitted by the C standard, so it is conforming.


推荐阅读