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]因此是无效的.
你有一个数组数组. 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.