以下程序是C语言的严格遵从程序吗?我对c90和c99感兴趣,但c11的答案也可以接受。
在不同问题的答案评论中,Eric Postpischil坚持认为程序输出将根据平台而变化,主要是由于未初始化的填充位可能性。我认为结构体赋值将覆盖
#include <stdio.h>
#include <string.h>
struct S { int array[2]; };
int main () {
struct S a = { { 1, 2 } };
struct S b;
b = a;
if (memcmp(b.array, a.array, sizeof(b.array)) == 0) {
puts("ok");
}
return 0;
}
在不同问题的答案评论中,Eric Postpischil坚持认为程序输出将根据平台而变化,主要是由于未初始化的填充位可能性。我认为结构体赋值将覆盖
b
中的所有位,使其与a
中的位相同。但是,C99似乎没有提供这样的保证。来自第6.5.16.1节第2段:
在简单赋值(
=
)中,右操作数的值被转换为赋值表达式的类型,并替换左操作数指定的对象中存储的值。
在复合类型的情况下,“转换”和“替换”的含义是什么?
最后,考虑相同的程序,只是a
和b
的定义是全局的。那个程序将是一个严格符合规范的程序吗?
编辑:只想总结一些讨论材料,不添加我自己创作的答案。
- 该程序不是严格符合标准的。由于赋值是按值而不是按表示方式进行的,因此b.array可能包含与a.array不同的位设置。
- a不需要转换,因为它与b是相同类型,但替换是按成员逐个进行的。
- 即使在a和b的定义被全局化之后,在赋值后,b.array可能包含与a.array不同的位设置。(关于b中的填充字节的讨论很少,但发布的问题并不是关于结构比较的。c99缺乏有关静态存储器中填充如何初始化的说明,但c11明确指出它被零初始化。)
- 顺便说一句,如果b是通过从a中使用memcpy初始化的,则有共识认为memcmp是定义良好的。
感谢所有参与讨论的人。
struct
,而只是比较了数组。因此,在你提供的这个例子中,仍然只有一个问题,即int
是否具有填充位或所谓的负零。这些事情在现代架构上不会发生。你真的需要考虑一个真正有填充字节(而不是填充位)的实际结构,这样问题才变得相关。 - Jens Gustedtmemcmp
与int
数组,而这个struct
被用于影响分配到b
持有的数组中。 - jxhmemcpy
是可以的。memcpy
和memcmp
基于字节进行操作,这些字节被视为unsigned char
。unsigned char
是唯一一个保证没有填充比特和所有表示具有不同值的数据类型。 - Jens Gustedt