这个memcpy会导致未定义的行为吗?
根据这一定义:这个memcpy会导致未定义的行为吗?,c,struct,constants,language-lawyer,C,Struct,Constants,Language Lawyer,根据这一定义: struct vector { const float x; const float y; }; 下面的代码段是否可能导致未定义的行为 struct vector src = {.x=1.0, .y=1.0}; struct vector dst; void *dstPtr = &dst; memcpy(dstPtr, &src, sizeof dst); gcc和clang不会发出任何警告,但会导致修改const限定类型 这个结构看起
struct vector {
const float x;
const float y;
};
下面的代码段是否可能导致未定义的行为
struct vector src = {.x=1.0, .y=1.0};
struct vector dst;
void *dstPtr = &dst;
memcpy(dstPtr, &src, sizeof dst);
gcc
和clang
不会发出任何警告,但会导致修改const限定类型
这个结构看起来很像被接受的答案中给出的,显然是一致的。我不明白我的示例如何会因此不一致。成员上的
const
-限定符让编译器假设——在对象初始化后——这些成员不得以任何方式更改,并且可能会相应地优化代码(例如,@Ajay Brahmakshatriya comment)
因此,有必要将初始化阶段与赋值将应用的后续阶段区分开来,即从何时开始,编译器可以假定对象已初始化并具有可依赖的有效类型
我认为你的例子与你所引用的公认答案之间有一个主要区别。在SO应答中,通过malloc
创建具有常量限定成员类型的目标聚合对象:
ImmutablePoint init = { .x = x, .y = y };
ImmutablePoint *p = malloc(sizeof *p);
memcpy(p, &init, sizeof *p);
根据关于如何访问对象的存储值的规则(参见本部分),目标对象将在执行memcpy
的过程中第一次获得其有效类型;然后,有效类型是源对象init
的有效类型,而获取malloced
的对象上的第一个memcpy
可以视为初始化。然而,之后修改目标对象的const成员将是UB(我认为即使是第二个memcpy
也将是UB,但这可能是基于观点的)
6.5表达式
dst
已经通过其定义struct vector dst声明了一个类型代码>。因此,在应用memcpy
之前,dst
成员上的常量限定符已经就位,并且必须将其视为赋值而不是初始化
所以在这种情况下我会投UB的票 请参阅OP的最后一个问题:struct
具有const
成员的struct不能通过赋值进行设置,只能通过初始化进行设置(您对src
执行此操作)。memcpy
类似于赋值。从struct
中删除const
,事情就会好起来。在我看来,结构成员上的const
并没有那么有用,因为正是您遇到的问题。请注意,memcpy
即使使用const
也不会损害任何东西,但这是一种不好的做法。@CraigEstey它可能会造成伤害。考虑代码-<代码> {Stultvector Foo= {…};浮点A= Fo.x;MimcPy(and Fo,…,siZeof(FoO));int b= fo.x;}。编译器可以重用a
的值来设置b
。这似乎是个好问题,不知道为什么有人否决了它(尽管最后一段没有必要)。我不明白为什么这个问题被否决了;这是一个合理的、精心设计的问题,我不认为这是一个直截了当的回答。谢谢你的回答,这是一个有趣的引用,似乎确实解释了它。但是,我在解释“没有声明类型的对象”时遇到问题。p
是否声明为不可变点*
?我不这么认为p
是一个与它所指向的对象不同的对象p
具有声明的类型ImmutablePoint*
,但它指向的对象甚至还没有创建。好的,我不完全清楚“object”在本文中的含义。我还发现在“malloc函数为大小由size指定且其值不确定的对象分配空间”中,我想,它的类型也不确定。我仍然想在这段代码中添加这一点-foo(const char*t){char s=*t;某些函数调用(t);char r=*t;}
,即使t
标记为指向const
限定的char
,编译器也无法优化第二次读取。这是因为t
最初可能并不指向const
对象,而且某些函数调用修改内容是完全有效的。但是这种情况很特殊,因为常量在结构内部。任何指针的字段都将始终是const
@ReinierTorenbeek,由malloc
分配的对象还没有类型。它们可以通过写入对象来设置有效类型。