代码的有效性

Pra*_*rav 14 c++ undefined-behavior

请考虑以下代码:

void populate(int *arr)
{
   for(int j=0;j<4;++j)
       arr[j]=0;
}

int main()
{
   int array[2][2];
   populate(&array[0][0]);
}
Run Code Online (Sandbox Code Playgroud)

有在当地社区的代码是否有效与否对此的讨论(我应该提它的名字吗?).一个人说它调用UB是因为它违反了

C++标准版($ 5.7/5 [expr.add])

"如果指针操作数和结果指向相同的数组对象,或一个过去的数组对象的最后一个元素的元素两者,所述评估也不得产生溢出; 否则,该行为是未定义 ".

但是我没有看到代码有什么问题,代码对我来说完全没问题.

所以,我只是想知道这段代码是否有效?我错过了什么吗?

Gre*_*ill 15

你的array是两个数组int[2],而你的函数populate()将它视为单个数组int[4].根据编译器决定如何对齐元素的确切方式array,这可能不是一个有效的假设.

具体来说,当j你是2并且你试图访问时arr[2],这超出了mains 的范围,array[0]因此是无效的.

  • @Alok:在C++中,多维数组与指针数组不同.Java只有后者,但C和C++都有两种形式. (3认同)

Alo*_*hal 9

你有一个数组数组. array[1]array[0]在内存中,因为数组是连续的.如果p == array[0],则p[1]接下来p[0],因为数组是连续的.所以,你是对的:所有的记忆array都是连续的.

在图片中,array看起来像这样.

+-----------------+-----------------+
|      [0]        |      [1]        |
+-----------------+-----------------+
Run Code Online (Sandbox Code Playgroud)

现在,让我们打破array[0]array[1],它们分别是这样的:

+--------+--------+
|  [0]   |  [1]   |        
+--------+--------+
Run Code Online (Sandbox Code Playgroud)

所以,最后的图片是:

+--------+--------+--------+--------+
| [0][0] | [0][1] | [1][0] | [1][1] |
+--------+--------+--------+--------+
Run Code Online (Sandbox Code Playgroud)

现在,问题是,你能否按照自己的方式访问这个连续的内存.答案是,标准不保证.数组是连续的,但标准不允许以您的方式编制索引.换一种说法:

&array[0][0]+2 == &array[1][0],但(&a[0][0] + 2) + 1未定义,而&a[1][0] + 1有效.如果这看起来很奇怪,那么,根据您从标准中发布的引用,您只能计算一个指针,该指针位于数组内部或最多一个超过数组的指针(不解除引用"一个过去"指针) .

在实践中,我怀疑这会在任何地方失败,但至少根据标准,你的代码因未定义的行为而无效.

也请看这篇文章comp.lang.c.