简单赋值运算符和对象重叠 [英] Simple assignment operator and object overlap

查看:91
本文介绍了简单赋值运算符和对象重叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在语义学中看到了以下段落。

部分在N1124简单分配(C99草案),我想知道我是否

正确解释它:


6.5.16.1p3:

如果从另一个对象中读取存储在对象中的值

以任何方式重叠

存储第一个对象,然后重叠应该是准确的并且

两个对象应该是b $ b具有兼容类型的合格或不合格版本;否则,

行为是

undefined。


存储两个对象重叠的唯一可行方式/>
一个赋值上下文(我能想到的)是在存储到类型T的对象的

新值是*
的结果的情况下
运算符对类型''指向T'的对象'(或指向

不同类型的指针转​​换为''指向T''),其中指针指向a

被分配对象中的有效位置。对我来说,这是很多

的措辞,所以希望以下代码片段

说明我的意思:


/ *假设sizeof int> = 2 * /


int main(无效)

{

int i = 10;

int * ip =& i;


i = * ip; / *虽然没有意义,但这似乎是允许的\

*因为虽然i和* ip \

*的存储重叠,但重叠是准确的* /


++ ip; / *准备(可能)导致一些UB :-) * /


i = * ip; / *从我的理解,这是UB \

*因为i和* ip \

*的存储重叠(ip指向一个位置\

*由i的存储占用\\ n \\ n \\ n \\ n

*但ip是-not-指向最低的\

*可寻址字节我,因此\

*重叠是不确切的,它是未定义的* /

返回0;

}


DId我正确阅读了标准,并且是我的例子说明了

6.5.16.1p3打算通信的内容?如果没有,请直接设置我的

(并且,如果还有其他情况,重叠可以在分配中发生
除了尝试从
它自己的存储空间,这很有趣,因为我的例子是

无耻的设计。


-

Mike S

I came across the following paragraph in the "Semantics" section for
simple assignment in N1124 (C99 draft) and I''m wondering if I''m
interpreting it right:

6.5.16.1p3:

If the value being stored in an object is read from another object that
overlaps in any way
the storage of the first object, then the overlap shall be exact and
the two objects shall
have qualified or unqualified versions of a compatible type; otherwise,
the behavior is
undefined.

The only concievable way for the storage of two objects to overlap in
an assignment context (that I can think of) is in the case where the
new value being stored to an object of type T is the result of the *
operator on an object of type ''pointer to T'' (or a pointer to a
different type cast to ''pointer to T''), where the pointer points to a
valid location within the object being assigned to. That''s a lot of
verbiage on my part, so hopefully the following code snippet
illustrates what I mean:

/* assume sizeof int >=2 */

int main(void)
{
int i = 10;
int *ip = &i;

i = *ip; /* although pointless, this seems to be allowed \
* because although the storage of i and *ip \
* overlaps, the overlap is exact */

++ip; /* get ready to (potentially) cause some UB :-) */

i = *ip; /* from my understanding, this is UB \
* because the storage of i and *ip \
* overlaps (ip is pointing at a location \
* occupied by the storage of i) \
* but ip is -not- pointing at the lowest \
* addressable byte of i, thus the \
* overlap is not exact and it''s undefined */
return 0;
}

DId I read the Standard correctly and is my example illustrative of
what the 6.5.16.1p3 intends to communicate? If not, please set my
straight (and also, if there are other instances where overlap can
occur in an assignment besides trying to assign an object a value from
its own storage, that would be interesting to know, as my example is a
shamelessly contrived one).

--
Mike S

推荐答案

Mike S写道:
Mike S wrote:

我在语义学中遇到了以下段落。

部分在N1124简单分配(C99草案),我想知道我是否

正确解释它:


6.5.16.1p3:

如果从另一个对象中读取存储在对象中的值

以任何方式重叠

存储第一个对象,然后重叠应该是准确的并且

两个对象应该是b $ b具有兼容类型的合格或不合格版本;否则,

行为是

undefined。


存储两个对象重叠的唯一可行方式/>
一个赋值上下文(我能想到的)是在存储到类型T的对象的

新值是*
的结果的情况下
运算符对类型''指向T'的对象'(或指向

不同类型的指针转​​换为''指向T''),其中指针指向a

被分配对象中的有效位置。对我来说,这是很多

的措辞,所以希望以下代码片段

说明我的意思:


/ *假设sizeof int> = 2 * /


int main(无效)

{

int i = 10;

int * ip =& i;


i = * ip; / *虽然没有意义,但这似乎是允许的\

*因为虽然i和* ip \

*的存储重叠,但重叠是准确的* /


++ ip; / *准备(可能)导致一些UB :-) * /


i = * ip; / *从我的理解,这是UB \

*因为i和* ip \

*的存储重叠(ip指向一个位置\

*由i的存储占用\\ n \\ n \\ n \\ n

*但ip是-not-指向最低的\

*可寻址字节我,因此\

*重叠并不准确,它是未定义的* /

返回0;

}
I came across the following paragraph in the "Semantics" section for
simple assignment in N1124 (C99 draft) and I''m wondering if I''m
interpreting it right:

6.5.16.1p3:

If the value being stored in an object is read from another object that
overlaps in any way
the storage of the first object, then the overlap shall be exact and
the two objects shall
have qualified or unqualified versions of a compatible type; otherwise,
the behavior is
undefined.

The only concievable way for the storage of two objects to overlap in
an assignment context (that I can think of) is in the case where the
new value being stored to an object of type T is the result of the *
operator on an object of type ''pointer to T'' (or a pointer to a
different type cast to ''pointer to T''), where the pointer points to a
valid location within the object being assigned to. That''s a lot of
verbiage on my part, so hopefully the following code snippet
illustrates what I mean:

/* assume sizeof int >=2 */

int main(void)
{
int i = 10;
int *ip = &i;

i = *ip; /* although pointless, this seems to be allowed \
* because although the storage of i and *ip \
* overlaps, the overlap is exact */

++ip; /* get ready to (potentially) cause some UB :-) */

i = *ip; /* from my understanding, this is UB \
* because the storage of i and *ip \
* overlaps (ip is pointing at a location \
* occupied by the storage of i) \
* but ip is -not- pointing at the lowest \
* addressable byte of i, thus the \
* overlap is not exact and it''s undefined */
return 0;
}



增加后,i和* ip的存储不重叠,

但你仍然设法调用未定义的行为。我认为

声明ip作为指向unsigned char的指针会更好

适合你的查询。

After the increment, the storage of i and *ip do not overlap,
but you''ve still managed to invoke undefined behavior. I think
declaring ip as a pointer to an unsigned char would be better
suited to your query.


DId我正确阅读了标准,并且是我的例子说明了

6.5.16.1p3打算通信的内容?如果没有,请直接设置我的

(并且,如果还有其他情况,重叠可以在分配中发生
除了尝试从
它自己的存储空间,有趣的是要知道,因为我的例子是一个无耻制作的例子。)
DId I read the Standard correctly and is my example illustrative of
what the 6.5.16.1p3 intends to communicate? If not, please set my
straight (and also, if there are other instances where overlap can
occur in an assignment besides trying to assign an object a value from
its own storage, that would be interesting to know, as my example is a
shamelessly contrived one).



工会也许?

A union perhaps?


" Mike S" < mg ****** @ netscape.netwrites:
"Mike S" <mg******@netscape.netwrites:

我在语义学中遇到了以下段落。

部分在N1124简单分配(C99草案),我想知道我是否

正确解释它:


6.5.16.1p3:

如果从另一个对象读取存储在对象中的值

以任何方式重叠存储第一个对象,然后

重叠是准确的,两个对象应具有合格或

不兼容版本的兼容类型;否则,行为

未定义。


存储两个对象重叠的唯一可行方式

一项任务上下文(我能想到的)是这样的情况,即存储到类型T的对象的

新值是对象上的*

运算符的结果类型''指向T'的指针'(或指向

不同类型的指针转​​换为''指向T''),其中指针指向

被分配对象中的有效位置。对我来说,这是很多

的措辞,所以希望以下代码片段

说明我的意思:


/ *假设sizeof int> = 2 * /


int main(无效)

{

int i = 10;

int * ip =& i;


i = * ip; / *虽然没有意义,但这似乎是允许的\

*因为虽然i和* ip \

*的存储重叠,但重叠是准确的* /
I came across the following paragraph in the "Semantics" section for
simple assignment in N1124 (C99 draft) and I''m wondering if I''m
interpreting it right:

6.5.16.1p3:

If the value being stored in an object is read from another object
that overlaps in any way the storage of the first object, then the
overlap shall be exact and the two objects shall have qualified or
unqualified versions of a compatible type; otherwise, the behavior
is undefined.

The only concievable way for the storage of two objects to overlap in
an assignment context (that I can think of) is in the case where the
new value being stored to an object of type T is the result of the *
operator on an object of type ''pointer to T'' (or a pointer to a
different type cast to ''pointer to T''), where the pointer points to a
valid location within the object being assigned to. That''s a lot of
verbiage on my part, so hopefully the following code snippet
illustrates what I mean:

/* assume sizeof int >=2 */

int main(void)
{
int i = 10;
int *ip = &i;

i = *ip; /* although pointless, this seems to be allowed \
* because although the storage of i and *ip \
* overlaps, the overlap is exact */



到目前为止,我觉得很好。

So far, so good, I think.


++ ip; / *准备好(可能)导致一些UB :-) * /
++ip; /* get ready to (potentially) cause some UB :-) */



这会导致ip在i之后指向一个int对象;如果

sizeof(int)== 4,它会导致ip前进4个字节。

This causes ip to point to an int object just after i; if
sizeof(int)==4, it causes ip to advance by 4 bytes.


i = * ip; / *从我的理解,这是UB \

*因为i和* ip \

*的存储重叠(ip指向一个位置\

*由i的存储占用\\ n \\ n \\ n \\ n

*但ip是-not-指向最低的\

*可寻址字节我,因此\

*重叠是不确切的,它是未定义的* /
i = *ip; /* from my understanding, this is UB \
* because the storage of i and *ip \
* overlaps (ip is pointing at a location \
* occupied by the storage of i) \
* but ip is -not- pointing at the lowest \
* addressable byte of i, thus the \
* overlap is not exact and it''s undefined */



不,我和* ip don不重叠,但取消引用ip调用undefined

行为,因为ip没有指向一个对象。


你可以让我成为一个数组2个整数,并进行一些指针转换

将ip增加1个字节而不是sizeof(int)字节,但是然后

dereferencing ip会调用未定义的行为,如果它'没有对齐

正确。如果实现允许1个字节对齐整数,并且

如果sizeof(int)> = 2,如上所述,那么这将是一个

(相当做作) )6.5.16.1p3正在讨论的例子。

No, i and *ip don''t overlap, but dereferencing ip invokes undefined
behavior, since ip doesn''t point to an object.

You could make i an array of 2 ints, and do some pointer conversions
to increment ip by 1 byte rather than by sizeof(int) bytes, but then
dereferencing ip would invoke undefined behavior if it''s not aligned
properly. If the implementation allows 1-byte alignment for ints, and
if sizeof(int) >= 2 as you mentioned above, then this would be a
(rather contrived) example of what 6.5.16.1p3 is talking about.


返回0;

}


DId我正确阅读了标准,并且是我的例子说明了什么是6.5.16.1p3打算通信的
?如果没有,请直接设置我的

(并且,如果还有其他情况,重叠可以在分配中发生
除了尝试从
它自己的存储空间,有趣的是要知道,因为我的例子是一个无耻制作的例子。)
return 0;
}

DId I read the Standard correctly and is my example illustrative of
what the 6.5.16.1p3 intends to communicate? If not, please set my
straight (and also, if there are other instances where overlap can
occur in an assignment besides trying to assign an object a value from
its own storage, that would be interesting to know, as my example is a
shamelessly contrived one).



您可以使用联合构建一个设计较少的例子。这就是我想要的b $ b:b
#include< stdio.h>

# include< stdlib.h>


int main(无效)

{

struct big_type {

int arr [32];

};

struct s1 {

char c;

struct big_type bt1;

};

struct s2 {

long long x;

struct big_type bt2;

};

union u {

struct s1 sub1;

struct s2 sub2;

} obj;


printf(" obj.sub1.bt1,offset =%d,size =%d \ n",

(int) offsetof(union u,sub1.bt1),

(int)sizeof obj.sub1.bt1);

printf(" obj.sub2.bt2,offset =% d,size =%d \ n",

(int)offsetof(union u,sub2.bt2),

(int)sizeof obj.sub2.bt2) ;


/ *

*初始化bt1所以我们可以在不调用UB的情况下引用它。

* /

memset(& obj.sub1.bt1,0,sizeof obj.s ub1.bt1);

/ *

*现在将其值赋给bt2。如果bt1和bt2重叠,则

*调用未定义的行为。

* /

obj.sub2.bt2 = obj.sub1.bt1;


返回0;

}


我得到的输出是:


obj.sub1.bt1,offset = 4,size = 128

obj.sub2.bt2,offset = 8,size = 128


所以obj.sub1.bt1和obj.sub2.bt2重叠,但不完全,并且

他们都正确对齐。 (一个实现可以指定它们

两个相同的偏移量,所以程序没有*无条件*调用

未定义的行为。)


可以使用等效的memcpy()来完成赋值;它没有
必须使用相当于memmove()的东西。


-

Keith Thompson(The_Other_Keith) ks***@mib.org < http://www.ghoti.net/~kst>

圣地亚哥超级计算机中心< *< http://users.sdsc.edu/~kst>

我们必须做点什么。这是事情。因此,我们必须这样做。

You can build a less contrived example using unions. Here''s what I''ve
come up with:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
struct big_type {
int arr[32];
};
struct s1 {
char c;
struct big_type bt1;
};
struct s2 {
long long x;
struct big_type bt2;
};
union u {
struct s1 sub1;
struct s2 sub2;
} obj;

printf("obj.sub1.bt1, offset = %d, size = %d\n",
(int)offsetof(union u, sub1.bt1),
(int)sizeof obj.sub1.bt1);
printf("obj.sub2.bt2, offset = %d, size = %d\n",
(int)offsetof(union u, sub2.bt2),
(int)sizeof obj.sub2.bt2);

/*
* Initialize bt1 so we can refer to it without invoking UB.
*/
memset(&obj.sub1.bt1, 0, sizeof obj.sub1.bt1);
/*
* Now assign its value to bt2. If bt1 and bt2 overlap, this
* invokes undefined behavior.
*/
obj.sub2.bt2 = obj.sub1.bt1;

return 0;
}

The output I get is:

obj.sub1.bt1, offset = 4, size = 128
obj.sub2.bt2, offset = 8, size = 128

so obj.sub1.bt1 and obj.sub2.bt2 overlap, but not completely, and
they''re both properly aligned. (An implementation could assign them
both the same offset, so the program doesn''t *unconditionally* invoke
undefined behavior.)

Assignment can be done using the equivalent of memcpy(); it doesn''t
have to use the equivalent of memmove().

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.




Keith Thompson写道:

Keith Thompson wrote:

迈克S < mg ****** @ netscape.netwrites:
"Mike S" <mg******@netscape.netwrites:

我在语义学中遇到了以下段落。

部分在N1124简单分配(C99草案),我想知道我是否

正确解释它:


6.5.16.1p3:

如果从另一个对象读取存储在对象中的值

以任何方式重叠存储第一个对象,然后

重叠是准确的,两个对象应具有合格或

不兼容版本的兼容类型;否则,行为

未定义。


存储两个对象重叠的唯一可行方式

一项任务上下文(我能想到的)是这样的情况,即存储到类型T的对象的

新值是对象上的*

运算符的结果类型''指向T'的指针'(或指向

不同类型的指针转​​换为''指向T''),其中指针指向

被分配对象中的有效位置。对我来说,这是很多

的措辞,所以希望以下代码片段

说明我的意思:


/ *假设sizeof int> = 2 * /


int main(无效)

{

int i = 10;

int * ip =& i;


i = * ip; / *虽然没有意义,但这似乎是允许的\

*因为虽然i和* ip \

*的存储重叠,但重叠是准确的* /
I came across the following paragraph in the "Semantics" section for
simple assignment in N1124 (C99 draft) and I''m wondering if I''m
interpreting it right:

6.5.16.1p3:

If the value being stored in an object is read from another object
that overlaps in any way the storage of the first object, then the
overlap shall be exact and the two objects shall have qualified or
unqualified versions of a compatible type; otherwise, the behavior
is undefined.

The only concievable way for the storage of two objects to overlap in
an assignment context (that I can think of) is in the case where the
new value being stored to an object of type T is the result of the *
operator on an object of type ''pointer to T'' (or a pointer to a
different type cast to ''pointer to T''), where the pointer points to a
valid location within the object being assigned to. That''s a lot of
verbiage on my part, so hopefully the following code snippet
illustrates what I mean:

/* assume sizeof int >=2 */

int main(void)
{
int i = 10;
int *ip = &i;

i = *ip; /* although pointless, this seems to be allowed \
* because although the storage of i and *ip \
* overlaps, the overlap is exact */



到目前为止,我觉得很好。


So far, so good, I think.


++ ip; / *准备好(可能)导致一些UB :-) * /
++ip; /* get ready to (potentially) cause some UB :-) */



这会导致ip在i之后指向一个int对象;如果

sizeof(int)== 4,则会导致ip前进4个字节。


This causes ip to point to an int object just after i; if
sizeof(int)==4, it causes ip to advance by 4 bytes.



哎呀...当然可以。当我写那个小宝石时,我的大脑正在用汇编语言思考

;-)正如Dingo所提到的,我应该使用

一个unsigned char *来表达我的观点。即使这样做,因为* ip可能

之后没有正确对齐,由此产生的未定义行为

也使我的实验无效,现在我想到了它。 。

Oops...Of course it does. My brain was thinking in assembly language
when I wrote that little gem ;-) As Dingo mentioned, I should have used
an unsigned char* to make my case. Even in doing so, since *ip might
afterwards not be aligned properly, the resulting undefined behavior
from that also invalidates my experiment, now that I think about it...


i = * ip; / *从我的理解,这是UB \

*因为i和* ip \

*的存储重叠(ip指向一个位置\

*由i的存储占用\\ n \\ n \\ n \\ n

*但ip是-not-指向最低的\

*可寻址字节我,因此\

*重叠是不确切的,它是未定义的* /
i = *ip; /* from my understanding, this is UB \
* because the storage of i and *ip \
* overlaps (ip is pointing at a location \
* occupied by the storage of i) \
* but ip is -not- pointing at the lowest \
* addressable byte of i, thus the \
* overlap is not exact and it''s undefined */



不,我和* ip don不重叠,但取消引用ip调用undefined

行为,因为ip没有指向一个对象。


你可以让我成为一个数组2个整数,并进行一些指针转换

将ip增加1个字节而不是sizeof(int)字节,但是然后

dereferencing ip会调用未定义的行为,如果它'没有对齐

正确。如果实现允许1个字节对齐整数,并且

如果sizeof(int)> = 2,如上所述,那么这将是一个

(相当做作) )6.5.16.1p3正在讨论的例子。


No, i and *ip don''t overlap, but dereferencing ip invokes undefined
behavior, since ip doesn''t point to an object.

You could make i an array of 2 ints, and do some pointer conversions
to increment ip by 1 byte rather than by sizeof(int) bytes, but then
dereferencing ip would invoke undefined behavior if it''s not aligned
properly. If the implementation allows 1-byte alignment for ints, and
if sizeof(int) >= 2 as you mentioned above, then this would be a
(rather contrived) example of what 6.5.16.1p3 is talking about.


返回0;

}


DId我正确阅读了标准,并且是我的例子说明了什么是6.5.16.1p3打算通信的
?如果没有,请直接设置我的

(并且,如果还有其他情况,重叠可以在分配中发生
除了尝试从
它自己的存储空间,有趣的是要知道,因为我的例子是一个无耻制作的例子。)
return 0;
}

DId I read the Standard correctly and is my example illustrative of
what the 6.5.16.1p3 intends to communicate? If not, please set my
straight (and also, if there are other instances where overlap can
occur in an assignment besides trying to assign an object a value from
its own storage, that would be interesting to know, as my example is a
shamelessly contrived one).



您可以使用联合构建一个设计较少的例子。这就是我想要的b $ b:b
#include< stdio.h>

# include< stdlib.h>


int main(无效)

{

struct big_type {

int arr [32];

};

struct s1 {

char c;

struct big_type bt1;

};

struct s2 {

long long x;

struct big_type bt2;

};

union u {

struct s1 sub1;

struct s2 sub2;

} obj;


printf(" obj.sub1.bt1,offset =%d,size =%d \ n",

(int) offsetof(union u,sub1.bt1),

(int)sizeof obj.sub1.bt1);

printf(" obj.sub2.bt2,offset =% d,size =%d \ n",

(int)offsetof(union u,sub2.bt2),

(int)sizeof obj.sub2.bt2) ;


/ *
*初始化bt1所以我们可以在不调用UB的情况下引用它。

* /

memset(& obj.sub1.bt1,0, sizeof obj.sub1.bt1);

/ *

*现在将其值赋给bt2。如果bt1和bt2重叠,则

*调用未定义的行为。

* /

obj.sub2.bt2 = obj.sub1.bt1;


返回0;

}


我得到的输出是:


obj.sub1.bt1,offset = 4,size = 128

obj.sub2.bt2,offset = 8,size = 128


You can build a less contrived example using unions. Here''s what I''ve
come up with:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
struct big_type {
int arr[32];
};
struct s1 {
char c;
struct big_type bt1;
};
struct s2 {
long long x;
struct big_type bt2;
};
union u {
struct s1 sub1;
struct s2 sub2;
} obj;

printf("obj.sub1.bt1, offset = %d, size = %d\n",
(int)offsetof(union u, sub1.bt1),
(int)sizeof obj.sub1.bt1);
printf("obj.sub2.bt2, offset = %d, size = %d\n",
(int)offsetof(union u, sub2.bt2),
(int)sizeof obj.sub2.bt2);

/*
* Initialize bt1 so we can refer to it without invoking UB.
*/
memset(&obj.sub1.bt1, 0, sizeof obj.sub1.bt1);
/*
* Now assign its value to bt2. If bt1 and bt2 overlap, this
* invokes undefined behavior.
*/
obj.sub2.bt2 = obj.sub1.bt1;

return 0;
}

The output I get is:

obj.sub1.bt1, offset = 4, size = 128
obj.sub2.bt2, offset = 8, size = 128



[...]


再次,正如Dingo所提到的,正如你在这里所展示的那样,工会可能是

最好的方式来说明这种标准是指

到。那应该是显而易见的,看看

union的整个概念是如何依赖于彼此重叠的物体;-)


-

Mike S

[...]

Again, as Dingo mentioned and as you show here, unions are probably the
best way to illustrate the kind of scenario the Standard is referring
to. That should''ve been obvious, seeing as how the entire concept of
union relies on objects overlapping one another ;-)

--
Mike S


这篇关于简单赋值运算符和对象重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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