jxh*_*jxh 26 c language-lawyer
以下程序是C中严格符合的程序吗?我对c90和c99感兴趣,但c11的答案也是可以接受的.
#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;
}
Run Code Online (Sandbox Code Playgroud)
在对不同问题的答案的评论中,Eric Postpischil坚持认为程序输出将根据平台而改变,主要是由于未初始化填充位的可能性.我认为结构赋值会覆盖所有位,b使其与in相同a.但是,C99似乎没有提供这样的保证.从第6.5.16.1节第2节:
在简单赋值(
=)中,右操作数的值将转换为赋值表达式的类型,并替换存储在左操作数指定的对象中的值.
在复合类型的背景下,"转换"和"替换"是什么意思?
最后,考虑相同的程序,除了定义a和b全局.请问该程序是严格符合程序?
编辑:只是想在这里总结一些讨论材料,而不是添加我自己的答案,因为我没有自己的创作.
b.array可能包含也可能不包含以不同方式设置的位a.array.a不需要转换,因为它是相同的类型b,但替换是按值,并由成员完成.a和b中的定义是全局的,后分配,b.array可能包含也可能不包含以不同方式设置的位a.array.(关于填充字节的讨论很少b,但是发布的问题不是关于结构比较.c99没有提到如何在静态存储中初始化填充,但是c11明确声明它是零初始化.)memcmp如果b用memcpyfrom 初始化,则一致认为已明确定义a.我要感谢所有参与讨论的人.
在 C99 \xc2\xa76.2.6 中
\n\n\n\n\n\xc2\xa76.2.6.1 常规
\n\n1 除本节所述外,所有类型的表示均未指定。
\n\n[...]
\n\n4 [..] 具有相同对象表示的两个值(NaN 除外)比较相等,但比较相等的值可能具有不同的对象表示。
\n\n6 当值存储在结构或联合类型的对象(包括成员对象)中时,与任何填充字节对应的对象表示形式的字节采用未指定的值。42)
\n\n42) 因此,例如,结构分配不需要复制任何填充位。
\n\n43) 具有相同有效类型 T 的对象 x 和 y 在作为类型 T 的对象访问时可能具有相同的值,但在其他上下文中具有不同的值。特别是,如果 == 是为类型 T 定义的,则 x == y 并不意味着 memcmp(&x, &y, sizeof (T)) == 0。此外,x == y 并不一定意味着 x 和 y具有相同的值;对 T 类型值的其他操作可能会区分它们。
\n\n\xc2\xa76.2.6.2 整数类型
\n\n[...]
\n\n2 对于有符号整数类型,对象表示的位应分为三组:值位、填充位和符号位。不需要任何填充位;[...]
\n\n[...]
\n\n5 任何填充位的值均未指定。[...]
\n
在 J.1 中未指定的行为
\n\n\n\n\n\n
\n\n- 在结构或联合中存储值时填充字节的值 (6.2.6.1)。
\n[...]
\n\n\n
\n- 整数表示中任何填充位的值 (6.2.6.2)。
\n
a因此,和的表示中可能存在一些b不同但不影响值的位。这与其他答案是相同的结论,但我认为标准中的这些引用将是很好的附加上下文。
如果你执行 amemcpy那么memcmp将始终返回 0 并且程序将严格符合要求。复制intomemcpy的对象表示。ab