7

在以下情况下,我有一个包含指向整数变量的指针的结构,如下所示:

struct Structure[] = { 
    { &Var[0], &Var[1] },
    { &Var[2], &Var[3] }
};

事情是:Var第一次填充此结构时未初始化。(如NULL:)不久之后(第一次传递)变量Var将被初始化并且引用将相应地更新。

我认为这没有任何故障的原因,但我希望您能提供专业知识。将无效内存(带有数组下标)的引用放入这样的数组中是否合法?或者我需要一种不同的方法来应对这种情况?

在第一次初始化之前,我不会访问这些变量的内容。

非常感谢。

编辑:为了未来读者的利益:Var是一个全局指针变量,在开始时被初始化为 NULL。初始化通过使用将其转换为数组new

4

3 回答 3

8

我假设这Var是一个指针对象,并且它的当前值是一个空指针。您的陈述暗示了这一点:

Var第一次填充此结构时未初始化。(如NULL:)

我还假设它Var没有在块范围内定义。如果它是在块范围内定义的,并且您没有对其进行初始化或为其分配值,那么它的值就是垃圾,不一定是空指针值,并且任何引用其值的尝试都有未定义的行为。

行为未定义。

如果Var == NULL,则&Var[N]具有未定义的行为。

arr[index]根据定义等价于*(arr + index),所以&Var[N]等价于&(*(Var + N))。指针算术的行为是根据指针指向的数组对象的元素定义的(单个对象被视为单元素数组),并且空指针不指向任何东西。

题外话:

C 明确表示&*x被评估为x,并且&[x[i])被评估为x+i; C++ 没有这样说,所以 的操作数&必须是有效的。C++ 有一个加法的特殊情况0,即使对于空指针也有很好的定义(C 没有这种特殊情况)。但&Var[0]在 C 和 C++ 中仍然无效,但原因不同。在 C 中,它等价于Var + 0,但添加0到空指针具有未定义的行为。在 C++ 中,它等同于Var + 0; 而是相当于&(*(Var + 0)); Var + 0是一个空指针,并且取消引用它具有未定义的行为。)

题外话结束。

是的,仅仅计算一个无效地址具有未定义的行为,即使它从未被取消引用。

这是 2011 ISO C++ 标准 5.7 [expr.add] 第 5 段中的相关文本;特别注意最后:

当具有整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向与原始元素偏移的元素,使得结果和原始数组元素的下标之差等于积分表达式。换句话说,如果表达式 P 指向数组对象的第 i 个元素,则表达式 (P)+N(等效于 N+(P))和 (P)-N(其中 N 的值为 n)指向分别指向数组对象的第 i + n 个和第 i - n 个元素,前提是它们存在。此外,如果表达式 P 指向数组对象的最后一个元素,则表达式 (P)+1 指向数组对象的最后一个元素,如果表达式 Q 指向数组对象的最后一个元素,则表达式 (Q)-1 指向数组对象的最后一个元素。如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则计算不应产生溢出;否则,行为未定义。

于 2013-08-05T15:11:31.607 回答
2

由于您直到第一次通过后才使用这些值,因此请做正确的事情并将结构的指针初始化为 null 。然后在你知道它们的时候输入正确的值。如果您采用这种方法,您的“是否合法”问题就会消失!

于 2013-08-05T15:15:33.693 回答
0

要回答具体问题(忘记示例代码):是的,您可以引用未初始化的内存,您根本无法取消引用它并期望定义的行为。

于 2013-08-05T15:48:18.967 回答