答案 0 :(得分:4)
正如其他答案所指出的,工会是最明显的安排方式。
这是一个更清晰的例子,说明内置赋值运算符可能会出现部分重叠的对象。如果不是部分重叠的对象限制,则此示例不会显示UB。
union Y {
int n;
short s;
};
void test() {
Y y;
y.s = 3; // s is the active member of the union
y.n = y.s; // Although it is valid to read .s and then write to .x
// changing the active member of the union, .n and .s are
// not of the same type and partially overlap
}
即使对于相同类型的对象,您也可能获得潜在的部分重叠。在short
严格大于char
的情况下,在X
未添加填充的实现中,请考虑此示例。
struct X {
char c;
short n;
};
union Y {
X x;
short s;
};
void test() {
Y y;
y.s = 3; // s is the active member of the union
y.x.n = y.s; // Although it is valid to read .s and then write to .x
// changing the active member of the union, it may be
// that .s and .x.n partially overlap, hence UB.
}
答案 1 :(得分:2)
union就是一个很好的例子 您可以使用重叠成员创建内存结构。
例如(来自MSDN):
union DATATYPE // Declare union type
{
char ch;
int i;
long l;
float f;
double d;
} var1;
现在,如果您使用 char 成员,则所有其他成员都是未定义的。那是因为它们位于相同的内存块中,并且您只为其中的一部分设置了实际值:
DATATYPE blah;
blah.ch = 4;
如果您尝试访问 blah.i 或 blah.d 或 blah.f ,则会有未定义的值。 (因为只有第一个字节,它是一个char,其值已设置)
答案 2 :(得分:1)
这是指指针别名的问题,这在C ++中被禁止,以便为编译器提供更容易的优化时间。可以在this thread
中找到对此问题的详细解释答案 3 :(得分:0)
可能是指严格的别名规则?内存中的对象不应与其他类型的对象重叠。
“严格别名是由C(或C ++)编译器做出的假设,取消引用指向不同类型对象的指针永远不会引用相同的内存位置(即彼此别名。)”
答案 4 :(得分:0)
规范示例使用memcpy:
char *s = malloc(100);
int i;
for(i=0; i != 100;++i) s[i] = i; /* just populate it with some data */
char *t = s + 10; /* s and t may overlap since s[10+i] = t[i] */
memcpy(t, s, 20); /* if you are copying at least 10 bytes, there is overlap and the behavior is undefined */
memcpy未定义行为的原因是因为没有必要的算法来执行复制。在这种情况下,memmove
被引入作为安全的替代方案。