【问题标题】:Preferred way to compare a structure to zero将结构与零进行比较的首选方法
【发布时间】:2012-01-23 18:20:06
【问题描述】:

今天我遇到了一种情况,我需要确定由大约 40 个元素组成的整个结构是否为零 - 这意味着每个元素都为零。
在考虑如何使其尽可能快速和高效时,我想到了 3 种不同的方法:

  1. 将每个元素与零进行比较,得到 40 个 if 语句。
  2. 分配一个类似的结构,该结构已经归零,并memcmp它与结构。
  3. 将结构包装在一个联合体中,并使用一个足够大的类型来覆盖所有结构。

例如

typedef union {
  struct {
    uint8_t a;
    uint8_t b;
    }
  uint16_t c;
 } STRUCTURE_A;

然后将其与零进行比较。

我想知道您对这些解决方案的看法,您认为哪种解决方案最快、最有效。
如果您有更好的方法,请告诉我...
谢谢。

【问题讨论】:

  • if 语句中简单地检查整个结构有什么问题,就像您可能会检查零标志一样?
  • 您是否分别实施了三种不同的方法并比较了它们的性能?你发现了什么?
  • 由于可能的填充,除了比较每个字段之外,我看不到一种可移植的方式
  • @Platinum - 填充位、未初始化的成员(可能并非所有有效数据配置都需要)、在概念上为“假”时可能为非零的成员,上述任何一项在随着您的应用程序扩展的未来。
  • 尽可能高效是否重要?

标签: c data-structures comparison


【解决方案1】:

将结构的每个成员与 0 进行比较。

这是比较两个结构对象的唯一安全方法(即使其中一个结构对象的所有成员都设置为值 0)。不要使用memcmp 比较结构,结构中填充字节的值是未指定的。另请注意,不允许将== 运算符与结构对象操作数一起使用。

查看这个关于结构对象比较的 c-faq 链接:

Q: Is there a way to compare structures automatically?

【讨论】:

  • 如果您确保结构不包含填充,memcmp 是安全的。虽然在技术上允许实现添加任意无意义的填充,但在现实世界中,填充纯粹是为了对齐,并且一个正确构造的、自然对齐的结构除了可能在末尾之外没有填充。特别是,使用intX_t 并在没有对齐间隙的情况下对它们进行排序是避免任何填充的好方法。
  • 如果结构不包含填充,并且 memcmp 实际上 更快,优化器肯定会看到并相应地转换您的比较。
【解决方案2】:

如果您的结构大小 if's,以便清晰但仍然保持性能达到标准。

【讨论】:

    【解决方案3】:

    为了代码清晰,正如其他人指出的那样,为了避免填充引起的问题,最好检查每个成员。

    为了速度,从这样的东西开始,它只检查每个字节以查看它是否为零。

    int iszero(void * ptr, int bytes )
    {
       char * bptr = (char*)ptr;
       while( bytes-- )
         if( *bptr++ )
             return 0;
      return 1;
    }
    

    然后进行优化以进行字对齐比较。查看 newlib 对 strlen()memcpy() 之类的实现,了解如何实现的示例。

    【讨论】:

    • 这相当于memcmp,可能有填充问题。
    • @R.. 不,它不等同于 memcmp() 因为这里没有多余的归零结构。 memcmp() 中的额外内存访问可能比内存访问时间加倍更糟糕,因为您每次执行两次读取,并且您可能在大型结构上进行缓存垃圾处理。我没有考虑填充问题。但是如果你知道没有填充(例如在 GCC 中使用 pragma pack),我会坚持我的论点,即这种技术是最快的。
    • “等效”是指它具有相同的行为(和填充问题),但我邀请您比较性能。您的代码(逐字节)太慢了,即使多次读取,memcmp 也应该获胜。一个好的memcmp 一次比较 4、8 甚至 16 个字节。顺便说一句,“打包”不是解决对齐问题的方法。我对 ouah 答案的评论是正确的方法。
    • @R..,我猜你错过了关于优化以进行字对齐比较(如 memcmp)的评论。我将其作为练习留给 OP,并提供 newlib 作为参考 impl。虽然是的,但您应该注意对结构中的字段进行排序以减少对填充的需求,这并不总是消除填充,而是将其移到最后。然后,当你有嵌套结构时,你的理论就会消失,因为你突然又在中间有填充。
    • @R..,我应该补充一点,我很清楚没有结构打包技术是完全可移植的,但是我在野外遇到的每个 C 编译器都有 一些打包结构的技术。我也知道,紧密包装你的结构可能会损害访问非对齐整数等的性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 2013-11-19
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    相关资源
    最近更新 更多