0

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与报告错误的方式(设备永远不会返回所有 0xFF 字节)。我有固定的平台和工具链,代码现在可以工作,但是如果我提高优化级别,我可以相信它不会中断吗?


结论:虽然如果我确保没有填充位、浮点字段等可能有问题,则可以使此代码正常工作,但我决定改为将一个特定的结构字段设置为特定的“不可能”值以指示错误。

4

2 回答 2

3

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

这同样适用于您的线路value2 = invalid_S;

于 2017-12-27T14:31:38.007 回答
1

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

是的,因为所有memsetmemcmpmemcpy都被记录在任意内存区域上工作(假设传递给它们的指针和大小指向一个有效的内存区域)。

但是,在某些情况下,这可能没有意义。例如,如果你memcpy从一些未初始化的内存中,你会在目的地得到垃圾,使用这些垃圾可能是未定义的行为

您正在使用memsetwith 0xff。理论上,您可能有一些 achar大于 8 位的实现(但实际上这不会发生,所以您不在乎)。

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

如果您memcmp在具有填充的结构上使用可能无法按预期工作。您可能想深入了解您平台的ABI规范以了解它们是如何实现的(并且位域可能未在您的 ABI 中指定并且是特定于编译器的)。

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

于 2017-12-27T14:25:10.130 回答