Which C99-compiler (Clang vs. GCC) is closer to standard on const structure fields?

非 Y 不嫁゛ 提交于 2019-12-17 20:48:56

问题


I have code like this:

$ cat test.c 
#include <stdio.h>
typedef struct
{
    const int x;
} SX;

static SX mksx(void)
{
    return (SX) { .x = 10 };
}

void fn(void)
{
    SX sx;
    while((sx = mksx()).x != 20)
    {
        printf("stupid code!");
    }
}

And 2 opinions about its correctness:

$ for i in gcc clang; do echo "$i SAYS:"; $i -c -std=c99 -pedantic -Werror test.c; done
gcc SAYS:
test.c: In function ‘fn’:
test.c:15:2: error: assignment of read-only variable ‘sx’
  while((sx = mksx()).x != 20)
  ^
clang SAYS:

Which compiler is right?


回答1:


The C99 standard says in 6.5.16:2:

An assignment operator shall have a modifiable lvalue as its left operand.

and in 6.3.2.1:1:

A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.

So GCC is right to warn.

In addition, the clause 6.5.16:2 is in a “Constraints” section of the C99 standard, so a conforming compiler is required to emit a diagnostic for a program that breaks the clause. It is still undefined behavior: the compiler can still do what it wants after the diagnostic is emitted. But there has to be a message. In consequence, Clang is behaving in a non-conforming manner here.




回答2:


const variable can't be modified after initialization, otherwise it's undefined behavior.

Since it is undefined behavior, I think one can say both gcc and clang follow the standard. (Although gcc's choice seems better, it deserves a warning) (See EDIT below)

The only way to give the variable x a value with defined behavior is to initialize it:

SX sx = { .x = 10 };

EDIT: As @Keith Thompson comments below, it's more than just undefined behavior in this case:

C99 §6.5.16 Assignment operators

Constraints

An assignment operator shall have a modifiable lvalue as its left operand.

This is a constraint, and according to:

C99 §5.1.1.3 Diagnostics

A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. Diagnostic messages need not be produced in other circumstances.

A compiler must issue a diagnostic for any program that violates a constraint.

Back to the question, gcc is correct is generate a warning, while clang fails to do so.



来源:https://stackoverflow.com/questions/18527984/which-c99-compiler-clang-vs-gcc-is-closer-to-standard-on-const-structure-fiel

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!