在C语言中,是否为 struct 定义了值的自赋值?

struct Foo { char value[4096]; };

struct Foo foo = {0};

struct Foo *p_foo = &foo;

foo = *p_foo;

在赋值之后是否定义了foo的值?假设指针是从另一个文件中的另一个函数传入的,因此不可能进行编译器优化(这与规范无关).

这种类型的赋值经常发生在像整型这样的简单类型中,但是对于更复杂(和更大)的 struct 呢?

在我的测试中,这似乎像预期的那样工作,但我试图找出这种预期应该有多强烈.

推荐答案

在C语言中,是否为 struct 定义了值的自赋值?

是的,对于所有可修改的数据类型,都很好地定义了自赋值,无论是通过指针还是其他方式.

我猜您担心重叠的某种问题,但从语义上讲,当赋值右侧的表达式是左值时,在执行赋值或计算赋值表达式的值之前,它需要进行左值转换以生成(瞬时)值.在语义上,对象的初始值是完全读取的,然后它的值是完全写入的(具有相同的内容,但也参见下文).

规范does说:

如果存储在对象中的值是从以任何方式与第一个对象的存储重叠的另一个对象中读取的,则重叠应该是精确的,并且两个对象应该具有兼容类型的限定或非限定版本;否则,行为是未定义的.

(C23 6.5.16.1/3)

但这要注意避免self 分配.

这种类型的赋值经常发生在像整型这样的简单类型中,但是对于更复杂(和更大)的 struct 呢?

对于不同的可修改数据类型,C语言规范在这方面没有不同的规则或规定.不管它有多大或多复杂.

在我的测试中,这似乎像预期的那样工作,但我试图找出这种预期应该有多强烈.

规范说它起作用了,在这个意义上,所有成员在self 赋值后都将具有与以前相同的值.然而,

当值存储在 struct 或联合类型的对象(包括成员对象)中时,与任何填充字节相对应的对象表示的字节将采用未指定的值

(C23 6.2.6.1/6)

.可以判断具有Any的 struct 值中的填充字节,并且以这种方式可以观察到 struct 类型的对象的自赋值以具有可识别的效果.但我认为这在实践中是不太可能的.

C++相关问答推荐

Pure Win32 C(++)-除了替换控件的窗口程序之外,还有其他方法可以在输入时禁用按钮吗?

当打印字符串时,为什么在c中没有使用常量限定符时我会收到警告?

在C语言中,是否可以使枚举数向后计数?

`#if`条件中是否允许`sizeof`?

如何在下面的C代码中正确管理内存?

C指针概念分段故障

cairo 剪辑区域是否存在多个矩形?

Boyer Moore算法的简单版本中的未定义行为

S和查尔有什么不同[1]?

通过描述符查找文件路径时出现问题

-Wnonnull-Compare警告不是具有误导性吗?

递归打印二维数组(C编程)

C编译和运行

在printf()中用%.*S格式填充长度为0的字符串是否会调用任何UB?如果是,是哪一个?

我编写这段代码是为了判断一个数字是质数、阿姆斯特朗还是完全数,但由于某种原因,当我使用大数时,它不会打印出来

为什么GCC不能在 struct 初始值设定项中以sizeof作为条件的三进制中处理复合文字的编译时求值?

通过char*访问指针的对象表示是未定义的行为吗?

在C中定义函数指针?

如何使用 raylib 显示数组中的图像

当循环变量在溢出时未定义时,可以进行哪些优化?