c - 在 int 数组上使用 memcmp 是否严格符合要求?

标签 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;
}

comments to my answer in a different question Eric Postpischil 坚持认为程序输出会根据平台的不同而改变,这主要是由于可能存在未初始化的填充位。我认为结构体赋值会覆盖 b 中的所有位,使其与 a 中的相同。但是,C99似乎并没有提供这样的保证。来自第 6.5.16.1 p2 节:

In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.

复合类型上下文中的“转换”和“替换”是什么意思?

最后,考虑同一个程序,只不过 ab 的定义是全局的。 那个程序会是一个严格遵守的程序吗?

编辑:只是想总结一下这里的一些讨论 Material ,而不是添加我自己的答案,因为我真的没有自己的创作。

  • 该程序不严格符合要求。由于分配是按值而不是按表示形式,因此 b.array 可能包含也可能不包含与 a.array 不同的位设置。
  • a 不需要转换,因为它与 b 类型相同,但替换是按值进行的,并且逐个成员完成。
  • 即使 ab 中的定义是全局的,赋值后,b.array 可能包含也可能不包含不同设置的位来自a.array。 (关于 b 中的填充字节的讨论很少,但发布的问题不是关于结构比较。c99 没有提及如何在静态存储中初始化填充,但 c11 明确指出它是零初始化的.)
  • 顺便说一句,如果 b 是使用 amemcpy 初始化的,那么 memcmp 是明确定义的。/

感谢所有参与讨论的人。

最佳答案

在 C99 §6.2.6 中

§6.2.6.1 General

1 The representations of all types are unspecified except as stated in this subclause.

[...]

4 [..] Two values (other than NaNs) with the same object representation compare equal, but values that compare equal may have different object representations.

6 When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values.42)

42) Thus, for example, structure assignment need not copy any padding bits.

43) It is possible for objects x and y with the same effective type T to have the same value when they are accessed as objects of type T, but to have different values in other contexts. In particular, if == is defined for type T, then x == y does not imply that memcmp(&x, &y, sizeof (T)) == 0. Furthermore, x == y does not necessarily imply that x and y have the same value; other operations on values of type T may distinguish between them.

§6.2.6.2 Integer Types

[...]

2 For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. There need not be any padding bits;[...]

[...]

5 The values of any padding bits are unspecified.[...]

在 J.1 中未指定的行为

  • The value of padding bytes when storing values in structures or unions (6.2.6.1).

[...]

  • The values of any padding bits in integer representations (6.2.6.2).

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

<小时/>

如果您执行memcpy,那么memcmp将始终返回0,并且程序将严格符合要求。 memcpya 的对象表示复制到 b 中。

关于c - 在 int 数组上使用 memcmp 是否严格符合要求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11994513/

相关文章:

c - 链表添加新的根元素

c++ - 为什么有两种通过指针调用函数的方式?

按非类型参数类型的 C++ 模板特化

c++ - 如何理解 "C++ allows sizeof(char*) != sizeof(int*)"?

c++ - 访问 float 的 4 个字节是否会破坏 C++ 别名规则

c++ - 为什么在 C/C++ 多维数组中 a[0] 与 a 相同?

c - 如何在 C 结构中访问指向二维数组的指针?

每 3 秒调用一次函数

c++ - 具有依赖类型的 c++11 可变参数函数模板重载是否含糊不清?

c - 是否在两个不在同一数组中的指针上比较相等性定义行为?