代码之家  ›  专栏  ›  技术社区  ›  Goswin von Brederlow

这不是应该给一个越界警告吗?

c c++
  •  3
  • Goswin von Brederlow  · 技术社区  · 5 年前

    int foo() {
      int x[10] = {0};
      int *p = &x[5];
      return p[~0LLU];
    }
    

    我知道越界警告不是标准所要求的,但是编译器会给出它们。我在问编译器在这里给出这样的警告是否正确。

    有什么理由认为代码应该是格式良好的吗?

    3 回复  |  直到 5 年前
        1
  •  4
  •   Jean-François Fabre Darshan Ambre    5 年前

    我认为这段代码应该对越界数组访问发出警告:

    一个像样的编译器 能够 数组 (gcc没有,但clang有: https://godbolt.org/z/lOvl5n )

    对于此代码段:

    int foo() {
      int x[10] = {0};  
      return x[~0LLU];  // or x[40] to make it simpler, same thing
    }
    

    <source>:3:10: warning: array index -1 is past the end of the array (which contains 10 elements) [-Warray-bounds]
    
      return x[~0LLU];
    
             ^ ~~~~~
    

    在您的例子中,“丢失”编译器的是您正在分配给一个指针(数组)

        2
  •  2
  •   dbush    5 年前

    C语言对数组的边界检查没有任何要求。这是它快速发展的部分原因。也就是说,编译器在某些情况下可以并且确实执行检查。

    例如,如果我用 -O3 在gcc中并替换 return p[~0LLU]; 具有 return p[10];

    x1.c: In function ‘foo’:
    x1.c:6:10: warning: ‘*((void *)&x+60)’ is used uninitialized in this function [-Wuninitialized]
       return p[10];
    

    如果我使用 -10 作为索引:

    gcc -g -O3 -Wall -Wextra -Warray-bounds -o x1 x1.c
    x1.c: In function ‘foo’:
    x1.c:6:10: warning: ‘*((void *)&x+-20)’ is used uninitialized in this function [-Wuninitialized]
       return p[-100];
    

    对你来说,似乎 这就是价值 ~0LLU 为了指针运算的目的,将转换为有符号值,并被视为-1。

    x :

    int foo() {
      int y[10] = {0};
      int x[10] = {0};
      int z[10] = {0};
      int *p = &x[5];
      printf("&x=%p, &y=%p, &z=%p\n", (void *)x, (void *)y, (void *)z);
      return p[10] + y[0] + z[0];
    }
    

    此代码不会产生任何警告,即使 p[10]

        3
  •  2
  •   eerorika    5 年前

    编辑:用标准引号完成重写:

    [dcl.阵列] ,下标运算符[]的解释方式如下 E1[E2] 与相同 *((E1)+(E2))

    指针操作数的。如果表达式 P 指向元素 x[i] 数组对象的 x 具有 n P + J J + P J 有价值吗 j x[i + j] 0 ≤ i + j ≤ n ;否则,行为未定义。

    因此 p[~0LLU] 被解释为 *(p + ~0LLU) x[5 + ~0LLU]

    5 + ~0LLU 在指数的有效范围内?给定该语言的整数转换规则,如果类型5是大小不大于的有符号类型,则所示表达式似乎定义良好 unsigned long long x[4] i 在描述行为的表达式中。它应该被解释为一个纯粹的数学表达式,在这种情况下,结果将是一个不可表示的指标 long long unsigned 当然比