【问题标题】:using array in condition在条件下使用数组
【发布时间】:2012-08-16 18:32:21
【问题描述】:

我想检查一个条件中的数组。让我们看下面这个简单的代码:

#include <stdio.h>
int main()
{
    int array[] = {1,2,3,4,5}; // initializing an array
    if(array[] == {1,2,3,4,5}) // using as condition
    {
         printf("worked");
    }
    else printf("not worked");

    return 0;
}

但它给出了一个错误:

In function 'main':|
C:\Python32\Untitled4.c|5|error: expected expression before ']' token|
||=== Build finished: 1 errors, 0 warnings ===|

那么我应该如何在条件中使用数组呢?

【问题讨论】:

    标签: c arrays


    【解决方案1】:

    如果你有一个现代 C 编译器,至少是 C99,你可以使用复合文字和函数来进行比较:

    if(memcmp(array, (int[]){1,2,3,4,5}, sizeof array) == 0) {
       printf("worked");
    }
    
    • 这里memcmp(内存比较)比较两者的数据 指针指向。
    • (int[]){1,2,3,4,5} 是复合文字,其类型为 (),然后是 { } 中的初始化器,就像您在变量声明中一样。
    • 当像在这样的表达式中使用时,这两个数组被转换为指向它们的第一个元素的指针

    编辑:正如 Eric 正确指出的那样,memcmp 只有在您的数组的基本类型(这里是 int)没有填充位或字节时才是有效的比较。对于int,如今这种情况并不常见,所以我所描述的在通常的平台上都很好。如果有一天您有其他更复杂的数据类型,您将不得不为该类型的数组编写自己的比较函数。

    【讨论】:

    • memcmp 不是执行比较的安全方法,因为即使是基本类型也可能有填充位。这将适用于常见平台上的基本类型数组,但通常不是标准 C,不可移植,不可移植,并且不适用于复杂类型(带有填充的结构)。
    • @EricPostpischil,对,请看我的编辑。对于downvoters,会更好地先告诉你不喜欢什么。 SO应该是一个友好的地方。
    【解决方案2】:

    这种格式:

    int array[]={1,2,3,4,5};
    

    只能在初始化或数组或结构中使用。这称为聚合初始化。这不能用于一般表示一个数组。

    此外,您不能使用== 来比较 C 中的数组或结构。

    要对您的条件进行编码,您需要检查每个值。

    【讨论】:

      【解决方案3】:

      另一个不同的“你可以用=赋值,但不能与==比较的例子是struct类型。

      struct S {
          int array[5];
      };
      
      struct S a = { { 1, 2, 3, 4, 5 } };
      struct S b;
      
      b = a; /* assignment ok */
      if (b == a) { /* equality not ok */ }
      

      那么我应该如何在条件中使用数组呢?

      你可以使用memcmp。

      if (memcmp(b.array, a.array, sizeof(b.array)) == 0) { /* ... */ }
      

      编辑:请注意,memcmp 对两个内存位置进行逐字节比较。正如 Eric 指出的那样,如果您的对象具有不同值的填充位,或者您的类型具有相同值的多个位表示,则 memcmp 可能会产生误报。

      在实践中,通过以标准化方式初始化对象(例如,在进行成员分配之前使用 memset 到 0 出内存),可以避免这个问题。 编辑: 即便如此,通过memcmp 进行的比较仍可能产生假阴性。执行比较的最大可移植方式是将每个对应的成员相互比较。 (Follow the link for the gory details.)

      您可以创建一个辅助函数来简化此操作:

      /* API as memcmp, but memory treated like array of int, remainder bytes ignored */
      int memcmp_int (const void *a, const void *b, size_t sz) {
          const int *aa = a;
          const int *bb = b;
          while (sz >= sizeof(int)) {
              if (*aa < *bb) return -1;
              if (*aa > *bb) return 1;
              ++aa;
              ++bb;
              sz -= sizeof(int);
          }
          return 0;
      }
      

      那么,就可以很简单地修改代码了:

      if (memcmp_int(b.array, a.array, sizeof(b.array)) == 0) { /* ... */ }
      

      【讨论】:

      • memcmp 不是一种安全的比较方式,因为即使是基本类型也可能有填充位。这将适用于常见平台上的基本类型数组,但通常不是标准 C,不可移植,并且不适用于复杂类型(带有填充的结构)。
      • @EricPostpischil:您能否详细说明“非标准 C”和“不可移植”的含义?
      • C 标准允许 C 实现在对象中包含填充位。 C 标准未指定这些填充位的值。它还允许某些对象具有多种表示形式(非填充位中的不同字节可能表示相同的值)。当您将对象与 memcmp 进行比较时,您将比较对象中的所有位,包括填充位和原始编码。您不是在比较对象的值。当对象实际上具有相等的值时,memcmp 可以返回假阴性(报告不相等)。
      • @EricPostpischil:我同意你对使用 memcmp 的局限性的评估,但这只是意味着该技术需要特殊措施来避免错误,而不是它不标准或不可移植。跨度>
      • 当然不便携。此代码的行为取决于 C 实现,并在某些实现上产生不希望的行为,而在其他实现上产生所需的行为。因此它不是可移植的:移植时它并不总是有效。至于它是否是标准 C,根据技术定义,它不能成为 C 1999 第 4 条第 5 段的“严格符合程序”的一部分(除非 memcmp 的结果在影响任何输出之前被丢弃)。它可以被认为(非严格)符合。
      【解决方案4】:

      您需要遍历数组。一个简单的循环如下所示:

      #include <stdio.h>
      int main()
      {
          int array[] = {1,2,3,4,5}; //initializing an array
          int iter = 0;
          for (; iter < sizeof(*array); iter++){
              printf("Iteration: %i\n", iter);
              // TOOD: Add your condition here
          }
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多