【问题标题】:Equality of structure using pragma pack in C在 C 中使用 pragma pack 的结构相等性
【发布时间】:2015-08-27 19:26:46
【问题描述】:

在 C 中无法检查结构是否相等的原因是存在松弛字节,这使得比较不可能。

但是如果我使用#pragma pack(1) 来删除松弛字节,那么比较应该可以顺利进行,但在比较时仍然会出错。

示例代码

#include<stdio.h>
#pragma pack(1)
struct person
{
    int uid;
    char nameStart;
};
struct personDupe
{
    int uid;
    char nameStart;
};
int main()
{
    struct person var;
    struct personDupe varDupe;
    printf("\nSize of person : %3d\n",sizeof(var));
    printf("\nSize of personDupe : %3d\n",sizeof(varDupe));

    var.uid = 12;
    var.nameStart = 'a';

    varDupe.uid = 12;
    varDupe.nameStart = 'a';

    if(var == varDupe)    //Error is introduced
        printf("\nStructures are equal\n");
    return 0;
}

【问题讨论】:

  • 你遇到了什么错误?
  • 第二个问题:如果你认为它们是平等的,为什么会有两种不同的类型?
  • @Bo Persson 第二种类型只是用于检查我脑海中关于 pragma pack 的逻辑,否则对于检查相等性 memcmp 很有帮助,正如 Jack 所建议的那样
  • @Bob Jarvis 错误:D:\Code\structEquality.c|26|错误:二进制 == 的操作数无效(有 'struct person' 和 'struct personDupe')|
  • 什么是“松弛字节”?

标签: c struct structure pragma


【解决方案1】:

您的代码无法编译,因为您无法直接比较两个 struct

你应该使用类似memcmp:

memcmp(&var, &varDupe, sizeof(var));

这并不能解决填充问题,可以通过确保结构正确初始化为已知值来解决,即使在填充字节上(可以在字段初始化之前通过memset 获得)。

但是打包 struct 以删除填充以检查它们是否相等的方法似乎是一个脆弱的解决方案。如果编译器想要填充,那么它有一个很好的理由,可能与性能有关。

【讨论】:

  • Memcmp 有时有点不安全,因为您可以在结构中进行填充。我认为明智地比较成员总是安全的。但是如果你强制不做padding,那么memcmp就可以了。
  • @Ritesh:仍然不行,因为如果在数组中使用,您仍然可以在结构的末尾使用填充来对齐 mext 元素。在 C 中,编译器无法知道。
【解决方案2】:

您还可以告诉编译器如何检测到两个值相同

bool same_person(struct person* p, struct personDupe* dupe)
{ return p->uid == dupe->uid && p->nameStart == dupe->nameStart; }

然后你就可以了

if(same_person(&var, &varDupe))
    printf("\nStructures are equal\n");

【讨论】:

  • 没关系,但是对于大量数据成员来说会很烦人,如果我们能有一些通用的解决方案就好了
  • @BigO C 不是带反射的语言,不可能有通用的解决方案
  • @BigO:您可以使用元编程来生成:结构和来自通用描述的比较函数。
  • @Olaf 你能举个例子吗?
  • @BigO:Pew,我前段时间回答了关于序列化的问题。这是一个类似的问题。如果你能找到它,你可以浏览我的答案。简而言之,这里的元编程意味着使用高级语言(我为此使用 Python)来生成您的 C 代码(或其中的一部分)。您可以使用 HLL 构造来描述您的 struct,并且 HLL 代码将为定义和所需功能(例如复制、比较等)生成周围的东西。这样,如果您将其集成到您的构建过程中,您就不必全部自己编写并保持一切一致。
猜你喜欢
  • 2010-12-04
  • 1970-01-01
  • 2015-06-20
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 2016-04-28
  • 1970-01-01
  • 2014-04-23
相关资源
最近更新 更多