这段代码可以调用未定义的行为吗? [英] Can this code invoke Undefined Behaviour?

查看:67
本文介绍了这段代码可以调用未定义的行为吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我和某人争论这段代码可以

调用undefined bahaviour。

我认为它没有调用任何未定义的行为,因为有

足够的9个整数元素的内存空间从

地址开始传递,但是另一个人坚持认为它会调用

未定义的行为(对于无论他有什么理由)。

void fill(int * p)

{

for(unsigned j = 0; j< 9; + + j)

p [j] = 0;

}


int main()

{

int arr [3] [3];

fill(& arr [0] [0]);

}

所以请告诉我这个代码是否会调用未定义的行为以及为什么?


Sharath AV

I had an argument with someone on wheather this piece of code can
invoke undefined bahaviour.
I think it does not invoke any undefined behaviour since there is
sufficient memory space of 9 integer elements starting from the in the
address passed, but the other person insisted that it would invoke
undefined behaviour(for whatever reasons he had).
void fill(int *p)
{
for(unsigned j=0;j<9;++j)
p[j]=0;
}

int main()
{
int arr[3][3];
fill(&arr[0][0]);
}
So please let me know if this code invokes undefined behaviour and why?

Sharath A.V

推荐答案

Sharath AV写道:
Sharath A.V wrote:

void fill(int * p)

{

for(unsigned j = 0; j< 9; ++ j)

p [j] = 0;

}


int main()

{

int arr [3] [3];

fill(& arr [0] [0] );

}
void fill(int *p)
{
for(unsigned j=0;j<9;++j)
p[j]=0;
}

int main()
{
int arr[3][3];
fill(&arr[0][0]);
}



我猜不会。但无论如何都不要这样做。


我怀疑数组数组的连续性是明确定义的。

表达式arr [3]与*(arr + 3)同义,因此arr [2] [2]是*(*(arr

+ 2)+ 2),代数转换为*(* arr + 2 * 3 + 2)。


现在问题是我的转换是如何形成良好和明确定义的。

然后,是同一个问题,还是答案的证明?


-

Phlip
http://c2.com/cgi/wiki?ZeekLand < - NOT a博客!!!

I''m going to guess no. But don''t do it anyway.

I suspect that the contiguity of arrays of arrays is well-defined. The
expression arr[3] is synonymous with *(arr + 3), hence arr[2][2] is *(*(arr
+ 2) + 2), which algebraically converts to *(*arr + 2 * 3 + 2).

Now the question is how well-formed and well-defined my transformation is.
Then, is it the same question, or a proof of the answer?

--
Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!!


Sharath AV写道:
Sharath A.V wrote:

我和某人发生了争执代码可以

调用undefined bahaviour。

我认为它不会调用任何未定义的行为,因为有
足够的9个整数元素的内存空间开始来自

地址通过,但另一个人坚持认为它会调用

未定义的行为(无论出于何种原因h)我有。)


无效填充(int * p)

{

for(无符号j = 0; j <9 ; ++ j)

p [j] = 0;

}


int main()

{

int arr [3] [3];

fill(& arr [0] [0]);

}


如果此代码调用未定义的行为,请告诉我。

为什么?
I had an argument with someone on wheather this piece of code can
invoke undefined bahaviour.
I think it does not invoke any undefined behaviour since there is
sufficient memory space of 9 integer elements starting from the in
the address passed, but the other person insisted that it would invoke
undefined behaviour(for whatever reasons he had).
void fill(int *p)
{
for(unsigned j=0;j<9;++j)
p[j]=0;
}

int main()
{
int arr[3][3];
fill(&arr[0][0]);
}
So please let me know if this code invokes undefined behaviour and
why?



AFAIK,标准保证在一个数组中所有元素一个接一个地放置

,没有间隙。多维数组也是如此。

也是如此。因此,int arr [3] [3]由3 * 3(9)紧密打包的元素组成,其中
类型为'int'',并将它们视为9个整数的单个数组即可。


V

-

请在通过电子邮件回复时删除资金''A'

我没有回复最热门的回复,请不要问

AFAIK, the Standard guarantees that in an array all elements are placed
one after another, without gaps. That''s true for multi-dimensional arrays
as well. So, int arr[3][3] consists of 3x3 (9) tightly-packed elements of
type ''int'', and treating them as a single array of 9 ints is OK.

V
--
Please remove capital ''A''s when replying by e-mail
I do not respond to top-posted replies, please don''t ask


Sharath AV写道:
Sharath A.V wrote:

我和某人有争执这段代码可以

调用undefined bahaviour。

我认为它不会调用任何未定义的行为,因为有

足够的9个整数元素的内存空间从

地址开始传递,但另一个人坚持认为它会调用

未定义的行为(无论他有什么理由)。


void fill(int * p)

{

for(unsigned j = 0; j< 9; ++ j)

p [j] = 0;

}


int main()

{

int arr [3] [3];

fill(& arr [0] [0]);

}


如果此代码调用未定义的行为以及原因,请告诉我。


Sharath AV
I had an argument with someone on wheather this piece of code can
invoke undefined bahaviour.
I think it does not invoke any undefined behaviour since there is
sufficient memory space of 9 integer elements starting from the in the
address passed, but the other person insisted that it would invoke
undefined behaviour(for whatever reasons he had).
void fill(int *p)
{
for(unsigned j=0;j<9;++j)
p[j]=0;
}

int main()
{
int arr[3][3];
fill(&arr[0][0]);
}
So please let me know if this code invokes undefined behaviour and why?

Sharath A.V



我认为这段代码可能会在

a绑定检查的实现中抛出异常(或类似的东西)。


相关的C ++标准段落是5.7 -5

[expr.add]


"如果指针操作数和结果都指向

的元素相同的数组对象,或者超过数组对象的最后一个元素,

评估不会产生溢出;否则,行为

未定义。


首先,p [4]相当于*(p + 4)。指针的类型是int *。

指针所指向的元素的类型是int


很明显,这是:

"如果指针操作数和结果都指向

相同数组对象的元素。

指针指向*元素*数组对象。指针

指向int,因此数组对象的类型为int [3]。


数组不是int [3] [3 ],否则它就没有意义......

int *指向一个int [3] ...所以它引用的数组对象是

第一个int [3]这个数组的对象是3 int [3]。


并且,p + 1没问题,p + 2没问题,p + 3没问题(指针一超过最后一个

元素),但是p + 4有未定义的行为。

如果执行绑定检查(并且WG21故意尝试

允许这样的实现)它可能会抛出一个运行时异常。

一个绑定检查的实现只会使用指针,不仅包括原始内存地址,而且还包含有关的信息。界限

数组直接这个元素。


同样,即使你有一个ABI说的实现:

struct X {

int x;

int y;

int z;

} s;


x,y和z在内存中是连续的。


这并不意味着你能够做到(& ; sx)[2]访问sz


的确,标准说(5.7-4 [expr.add])

"

4出于这些运算符的目的,指向非阵列

对象的指针与指向长度为1的

数组的第一个元素的指针的行为相同将对象的类型作为其元素类型。


嗯,这里很清楚& sx是指向非阵列的指针

对象,因此,绑定的已检查实现将使用大小为1的数组。

所以,(& sx)+ 1仍然可以......但是通过绑定检查实现,

(& sx)+1!= sy(绑定检查的实现将看到他们

don不住在相同的数组中。并且,(& sx)+2有UB。


嗯,我认为问题与int [3] [3]类似。

使用绑定检查的实现,& arr [3]应该不同于

& arr [1] [0]

例如,如果指针的底层实现是:

struct {raw_pointer start,ptr,end;};

& arr [3]的开始和结束与& arr [1]不同[0]

从某种意义上说,它们都生活在不同的记忆空间中。

I think this code might throw an exception (or something like that) on
a bound checked implementation.

The relevant C++ standard paragraph is 5.7-5
[expr.add]

"If both the pointer operand and the result point to elements of the
same array object, or one past the last element of the array object,
the evaluation shall not produce an overflow; otherwise, the behavior
is undefined."

First, p[4] is equivalent to *(p+4). The type of the pointer is int*.
The type of the element pointed-to by the pointer is int

It is clear, that:
"If both the pointer operand and the result point to elements of the
same array object."
The pointer points to an *element* of an array object. The pointer
points to int, and thus the array object is of type int[3].

The array is not an int[3][3], otherwise it would not make sense... an
int* pointing to an int[3]...So the array object to which it refers is
the first int[3] object of this array of 3 int[3].

And, p+1 is ok, p+2 is ok, p+3 is ok (pointer one past the last
element), but p+4 has undefined behavior.
If the implementation is bound checked (and the WG21 deliberately tried
to allow such implementation) it might throw a runtime exception.
A bound checked implementation would simply use pointers containing,
not only the raw memory address, but also information about the bounds
of the array directly this element.

Similarly, even if you have an implementation where the ABI says that:
struct X {
int x;
int y;
int z;
} s;

x, y and z are contiguous into memory.

It doesn''t mean that you''ll be able to do (&s.x)[2] to access s.z

Indeed, the standard says (5.7-4 [expr.add])
"
4 For the purposes of these operators, a pointer to a nonarray
object behaves the same as a pointer to the first element of an
array of length one with the type of the object as its element type."

Well, here it is very clear that &s.x is a pointer to a nonarray
object, and thus, a bound checked implementation will use, as bound
info, that it lives in an array of size 1.
So, (&s.x)+1 is still ok... But with a bound checked implementation,
(&s.x)+1 != s.y (the bound checked implementation will see that they
don''t live in the "same array"). And, (&s.x)+2 has UB.

Well, I think that the problem is similar with int[3][3].
With a bound checked implementation, &arr[3] should be different from
&arr[1][0]
For example, if the underlying implementation of pointers is:
struct {raw_pointer start, ptr, end;};
start and end will be different for &arr[3] than for &arr[1][0]
In a sense, they both live in different memory spaces.


这篇关于这段代码可以调用未定义的行为吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆