是否通过指向const未定义行为的指针修改对象?

jin*_*wee 4 c pointers const undefined-behavior language-lawyer

假设我们有一个int引用为的变量,const int*该变量又别名为int *。从标准中是否清楚通过int *指针修改变量是否为未定义行为?

作为说明,请考虑以下代码:

void increment(int* p) {
    (*p)++;
}

void call_increment(const int* p) {
    increment(p);
}

int main(void) {
    int x = 7;
    int* p = &x;

    call_increment(p);
}
Run Code Online (Sandbox Code Playgroud)

Ded*_*tor 8

通过指向对象的修改对象const是格式错误的行为,不是未定义的行为。除非引用的对象实际上是,否则
通过抛弃来解决该问题const是正确的const

您的代码有一个不同的问题:从传递给时,
您将丢弃const-qualifier 。pcall_increment()increment()

任何有用的编译器都会抱怨这一点,即使没有提示

g++ -x c -std=c18 main.cpp && ./a.out
main.cpp: In function 'call_increment':
main.cpp:6:15: warning: passing argument 1 of 'increment' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
     increment(p);
               ^
main.cpp:1:21: note: expected 'int *' but argument is of type 'const int *'
 void increment(int* p) {
                ~~~~~^
Run Code Online (Sandbox Code Playgroud)

请注意,最好至少要求更多-Wall -Wextra

  • 您应该提到将const int *转换回int *是有效的,并且由于C 2018 6.3.2.3 7而导致指向原始对象的指针:“指向对象类型的指针可能会转换为指向不同对象类型的指针。如果结果指针未针对引用类型正确对齐,则该行为未定义。否则,当再次转换回时,结果应等于原始指针。” (3认同)
  • @Lundin:第2段说您可以添加限定词。第7段说,您可以返回原始内容。第7段不是多余的,因为它允许您通过返回到较早的类型来删除最初不存在的限定符(但不能删除原来是对象定义一部分的限定符),第2段不涉及该限定符,因为它仅涉及添加限定符。 (2认同)