未定义的行为会更改文字数组吗?

时间:2019-07-19 17:28:40

标签: c arrays pointers undefined-behavior

我有以下情况:

#include <stdio.h>
struct A {
    double* a;
};
struct A data = {
    (double[]) {1.1, 1.2, 1.3}
};
void f() {
    data.a[2] = 2.2;
    printf("%f\n", data.a[2]); // situation 1
}

int main() {
    f();
    printf("%f\n", data.a[2]); // situation 2
}

我想知道两个标记的情况是否是未定义的行为。我相信情况1并不是不确定的行为(一旦我仅在data内使用f,情况2实际上就是这样。

如果不是不确定的行为,如果我将data.a[2] = 2.2;内的f更改为data.a = (double[]) {2.1, 2.2, 2.3};,我会得到不确定的行为吗?

2 个答案:

答案 0 :(得分:4)

  

我想知道两个标记的情况是否是未定义的行为   或不。我认为情况1并非未定义的行为(   仅在f)中使用数据,

C指定所有涉及的运算符的行为,并且对它们与示例代码中出现的对象或事件序列的使用没有限制。这样就定义了行为。

  

但是情况2实际上是。

C指定所有涉及的运算符的行为,并且对它们与示例代码中出现的对象或事件序列的使用没有限制。这样就定义了行为。

对象data是在文件范围内声明的,因此其生存期跨越程序的整个运行。它的一个成员使用指向表示为复合文字的数组的第一个元素的指针进行初始化,并且由于该复合文字出现在任何函数的主体之外,因此其生存期也跨越了程序的整个运行过程。此外,它的类型(在这种情况下)是double[3],它不是const限定的,因此可以将其元素分配给它。

  

在不是不确定行为的情况下,如果我更改数据。a[2] =   2.2;在data中的f里面。a =(double []){2.1,2.2,2.3} ;,我会得到未定义的行为吗?

是的,在main()中。出现在函数主体 中的复合文字具有自动持续时间,因此其生存期不迟于函数返回时。到那时,指向它或指向它的任何指针都变得不确定,并且任何取消引用它们的尝试(此后的main都具有不确定的行为)。

答案 1 :(得分:2)

您当前的代码非常好,数组复合文字是可变的。


  

在不是不确定行为的情况下,如果我更改数据。a[2] =   2.2;在data中的f里面。a =(double []){2.1,2.2,2.3} ;,我会得到未定义的行为吗?

如果你是这个意思,

void f() {
    data.a = (double[]) {2.1, 2.2, 2.3};
    printf("%f\n", data.a[2]); // situation 1
}

是的,这是未定义的行为,因为复合文字在作用域内是局部的。因此,您不能将它们用作参考,并且一旦控件退出该函数,它将消失。