这个 memset-memcmp 在结构变量上有效 C 吗?

Is this memset-memcmp on a struct variable valid C?

memset 将某个结构设置为某个值然后与 memcmp 进行比较是否合法?

struct S {
    // struct definition not relevant, but it has bitfields
};

struct S invalid_S;
memset(&invalid_S, 0xFF, sizeof invalid_S);

struct S value;
memset(&value, 0, sizeof value); // actual data read would be here

if (memcmp(&invalid_S, &value, sizeof(struct S) != 0) {
    /// operate on fields of value
}

struct S value2;
value2 = invalid_S;

if (memcmp(&invalid_S, &value2, sizeof(struct S) != 0) {
    /// operate on fields of value, which doesn't happen now
}

以上代码的行为是明确定义的、未定义的还是特定实现的?上述代码的有效性是否取决于 struct S?

将结构填充为 0xFF,然后将其与 memcmp 进行比较的原因是:我有一个函数,其中 return 是一个位域结构,与我从硬件中读取的内容相匹配设备,没有浪费的位或字节,我想要一种报告错误的有效方法(设备永远不会 return 所有 0xFF 字节)。我有固定的平台和工具链,代码现在可以在其中运行,但是我可以相信它不会因为我提高优化级别而崩溃吗?


结论:虽然如果我确保没有填充位、浮点字段等可能有问题,这段代码就可以工作,但我决定只将一个特定的结构字段设置为特定的 "impossible" 值指示错误。

Is it legal to memset a struct to some value, then compare it with memcmp?

是的,因为所有 memset, memcmp, memcpy 都记录在任意内存区域上(前提是传递给它们的指针和大小指向有效的内存区域)。

但是,在某些情况下,这可能没有意义。例如,如果您从一些 未初始化的 内存中 memcpy,您将在目标中获得垃圾,并且使用该垃圾可能是 undefined behavior.

您正在使用 memset0xff。理论上,您可能有一些 char 大于 8 位的实现(但实际上不会发生,所以您不关心)。

理论上,您可能有一些实现具有整数值的陷阱表示。实际上,这不会发生。

如果您在具有 padding that might not work as you expect. You may want to dive into the ABI 平台规范的结构上使用 memcmp 以了解它们是如何实现的(并且位域可能未在您的 ABI 中指定并且是特定于编译器的)。

我相信在实践中您需要很好地理解特定 struct 与特定编译器的确切布局。看起来您的代码可能是特定于硬件的,那么您就不太关心可移植性。所以在实践中你的 struct S 非常 相关的(也许避免其中的位域是 "safer")。

你说函数 returns 是一个“位域结构”。如果你真的是返回一个struct,也就是按值返回一个struct,那么不行,行为并不能保证是你想要的。复制结构时,实现只需要复制其成员中的值,而不是其表示中的实际字节。

同样适用于您的行 value2 = invalid_S;