【问题标题】:Why whole structure can not be compared in C, yet it can be copied?为什么整个结构在 C 中不能比较,但可以复制?
【发布时间】:2011-06-26 18:40:38
【问题描述】:

为什么整个结构不能在 C 中比较,但可以复制? 换句话说,为什么下面程序中的比较不起作用?它不打印字符串。

#include <stdio.h>
#include <string.h>

int main(void)
{

    struct emp
    {
        char n[20];
        int age;
        };

    struct emp e1={"David",23};
    struct emp e2=e1;
    if(e2 == e1)
    {
        printf("The structures are equal");
    }
    return(0);
}

【问题讨论】:

  • 因为运算符== 不知道它需要比较的结构的所有成员,所以你知道!
  • "它不打印字符串。"但它甚至不编译。 “错误:二进制 == 的操作数无效(有‘struct emp’和‘struct emp’)”
  • 你也不能在 C 中比较字符串 - 至少不能用 '==' 或等价物。 (struct emp){"David", 30}(struct emp){"Alfred", 20} 的顺序是什么,为什么?如果结构包含指向其他结构而不是简单字符串的指针怎么办?等等。
  • if (0 == memcmp(&amp;e1, &amp;e2, sizeof(struct emp))) { /* Structures are equal */ }

标签: c


【解决方案1】:

你可以使用 memcmp()。不过,这通常不是一个好主意,结构往往在字段之间有填充字节。填充用于对齐字段。你的结构没有,但那是偶然的。该填充可以具有任何类型的值,使 memcmp() 无法工作,因为它可以看到所有字节,而不仅仅是字段中的字节。

还有,结构中有一个 C 字符串。它可以包含零终止符之后的任何类型的字节。在字符串上使用 strcmp() 将返回 0 但 memcmp() 再次失败,因为它看到了所有字节。指针将是另一种失败模式。

一次比较一个字段。

【讨论】:

    【解决方案2】:

    struct 元素通常与某个边界对齐,并且当您初始化 struct(尤其是堆栈上的一个)时,对齐跳过的字节中的任何内容都将未初始化。此外,常量初始化器末尾之后的n 的内容不会被初始化。 struct 比较定义为 s1 == s2 执行 memcmp(&amp;s1, &amp;s2, sizeof s1),而 struct 初始化可能会或可能不会复制跳过的字节。如果您想可靠地比较structs,您应该明确比较它们的元素。

    【讨论】:

      【解决方案3】:

      它不打印字符串。

      但它甚至没有编译:

      error: invalid operands to binary == (have ‘struct emp’ and ‘struct emp’)
      

      【讨论】:

        【解决方案4】:

        除了已经说过的其他正确的事情之外,请记住,“比较”通常不是一件小事:它仅适用于“原始”基本类型。复杂类型(在这种情况下为结构)需要重载 ==,但 C 没有这样的概念。

        为了比较两个“对象”(结构),您必须编写自己的知道如何比较它们的函数,例如int compare_emp(const struct emp *, const struct emp *); 或类似的。

        【讨论】:

          【解决方案5】:

          只是一个想法,将其转换为 void * 之类的类型,然后比较工作? 我在想类似的东西

           struct emp e1 = { "David",23 };
           struct emp e2 = e1;
           if (*((void*)&e1) == *((void*)&e2))
           {
             /* pure evil? I think not :3*/
           }
          

          【讨论】:

          • 不,这不起作用的原因与代码无法编译的原因相同 - 你不能取消引用 void 指针,如果没有关联类型(以及大小),它就毫无意义。跨度>
          【解决方案6】:

          但是如果你将你的值传递给一个字符串,它会起作用吗?

          void Comparethisvalue(emp a, emp b) 
          {
              if(a.n.tostring()+a.age.tostring() == b.n.tostring()+b.age.tostring())
                return true; 
          }
          

          在你可以调用的代码中

          if(Comparethisvalue(e1, e2))
          {
            //do something
          }
          

          或者你可以隐式地这样做:

          void Comparethisvalue(emp a, emp b) 
          {
            if(a.n == b.n && a.age == b.age)
              return true; 
          }
          

          【讨论】:

          • 返回类型为 void 但您返回的是 true。
          猜你喜欢
          • 2010-12-25
          • 1970-01-01
          • 2015-01-17
          • 1970-01-01
          • 2013-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-03
          相关资源
          最近更新 更多