代码之家  ›  专栏  ›  技术社区  ›  hyde Juniar

结构变量上的memset memcmp是否有效?

  •  0
  • hyde Juniar  · 技术社区  · 7 年前

    这样做合法吗 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字节)。我有固定的平台和工具链,代码现在可以在这些平台和工具链上运行,但如果我提高优化级别,我能相信它不会崩溃吗?


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

    2 回复  |  直到 7 年前
        1
  •  3
  •   Eric Postpischil    7 年前

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

    这同样适用于您的产品线 value2 = invalid_S; .

        2
  •  1
  •   Basile Starynkevitch    7 年前

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

    是的,因为 memset , memcmp , memcpy 用于处理任意内存区域(前提是传递给它们的指针和大小指向有效内存区域)。

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

    您正在使用 memset 具有 0xff . 理论上,您可能有一些实现 char 大于8位(但实际上不会发生这种情况,所以您不在乎)。

    从理论上讲,您可能有一些实现具有积分值的陷阱表示。实际上,这并没有发生。

    如果您使用 memcmp 结构上有 padding 这可能不会像你预期的那样起作用。你可能想潜入 ABI 您的平台规范,以了解它们是如何实现的(位字段可能不会在您的ABI中指定,而是特定于编译器)。

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