在int数组上使用memcmp严格符合吗?

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节:

简单赋值(=)中,右操作数的值将转换为赋值表达式的类型,并替换存储在左操作数指定的对象中的值.

在复合类型的背景下,"转换"和"替换"是什么意思?

最后,考虑相同的程序,除了定义ab全局.请问程序是严格符合程序?

编辑:只是想在这里总结一些讨论材料,而不是添加我自己的答案,因为我没有自己的创作.

  • 该计划并不严格遵守.由于赋值是按值而不是表示,因此b.array可能包含也可能不包含以不同方式设置的位a.array.
  • a不需要转换,因为它是相同的类型b,但替换是按值,并由成员完成.
  • 即使在ab中的定义是全局的,后分配,b.array可能包含也可能不包含以不同方式设置的位a.array.(关于填充字节的讨论很少b,但是发布的问题不是关于结构比较.c99没有提到如何在静态存储中初始化填充,但是c11明确声明它是零初始化.)
  • 一方面,memcmp如果bmemcpyfrom 初始化,则一致认为已明确定义a.

我要感谢所有参与讨论的人.

Geo*_*edy 4

在 C99 \xc2\xa76.2.6 中

\n\n
\n

\xc2\xa76.2.6.1 常规

\n\n

1 除本节所述外,所有类型的表示均未指定。

\n\n

[...]

\n\n

4 [..] 具有相同对象表示的两个值(NaN 除外)比较相等,但比较相等的值可能具有不同的对象表示。

\n\n

6 当值存储在结构或联合类型的对象(包括成员对象)中时,与任何填充字节对应的对象表示形式的字节采用未指定的值。42)

\n\n

42) 因此,例如,结构分配不需要复制任何填充位。

\n\n

43) 具有相同有效类型 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\n

2 对于有符号整数类型,对象表示的位应分为三组:值位、填充位和符号位。不需要任何填充位;[...]

\n\n

[...]

\n\n

5 任何填充位的值均未指定。[...]

\n
\n\n

在 J.1 中未指定的行为

\n\n
\n
    \n
  • 在结构或联合中存储值时填充字节的值 (6.2.6.1)。
  • \n
\n\n

[...]

\n\n
    \n
  • 整数表示中任何填充位的值 (6.2.6.2)。
  • \n
\n
\n\n

a因此,和的表示中可能存在一些b不同但不影响值的位。这与其他答案是相同的结论,但我认为标准中的这些引用将是很好的附加上下文。

\n\n
\n\n

如果你执行 amemcpy那么memcmp将始终返回 0 并且程序将严格符合要求。复制intomemcpy的对象表示。ab

\n