对一个过去的数组元素进行指针运算,然后取消引用,结果会是什么?

Pointer arithmetic with one past array element and then dereference, what will be the outcome?

如果我取消引用数组并添加 5,这超出了数组中可用的元素,打印的值是什么?我在我的 IDE 中返回 32767,这没有多大意义。

#include <stdio.h>

int main(void)
{

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

    printf("%12s %18s %6s\n", "Element", "Address", "Value");

    for(i=0; i < 5; i++) {
        printf("meatBalls[%d] \t %p \t %d \n", i, &meatBalls[i], meatBalls[i]);
    }

    printf("\nmeatBalls \t\t %p \n", meatBalls); /*already a pointer*/

    /*dereference meatBalls and it will update to the value e.g. 1*/

    printf("\n*meatBalls \t\t %d \n", *meatBalls); /*dereference with asterisk*/

    printf("\n*(meatBalls+2) \t\t %d \n", *(meatBalls+2)); /*dereference but also go through the array from 0 + 2*/

    printf("\n*(meatBalls+4) \t\t %d \n", *(meatBalls+4));

    printf("\n*(meatBalls+5) \t\t %d \n", *(meatBalls+5)); /*what is the number that this returns?*/

    return 0;
}

这是当前输出,让我质疑“32767”:

     Element            Address  Value
meatBalls[0]     0x7fff5b714640      1 
meatBalls[1]     0x7fff5b714644      2 
meatBalls[2]     0x7fff5b714648      3 
meatBalls[3]     0x7fff5b71464c      4 
meatBalls[4]     0x7fff5b714650      5 

meatBalls        0x7fff5b714640 

*meatBalls       1 

*(meatBalls+2)       3 

*(meatBalls+4)       5 

*(meatBalls+5)       32767 

TL;DR: 不知道,不能说。

详细说明,在你的代码中

  printf("\n*(meatBalls+5) \t\t %d \n", *(meatBalls+5));

导致 undefined behavior 当您尝试 访问 超出限制的内存。

请注意 access 的强调。这种情况下的指针算法定义明确(最后一个元素之后),尝试访问导致 UB 的原因。

引用 C11,章节 §6.5.6(强调我的

[...] if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.

也就是说,%p 期望它的参数是 void* 并且由于 printf() 是一个可变参数函数,因此不会发生默认参数提升。因此,您需要将 %p 的所有参数转换为 (void *)

访问数组边界之外的元素是未定义的行为;所以你可以获得任何价值,但你的程序也可能崩溃。以下是 C standard 定义未定义行为的方式:

3.4.3 undefined behavior

behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements.

NOTE: Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

这就是标准定义您的访问是未定义行为的地方:

J.2 Undefined behavior

1 The behavior is undefined in the following circumstances:

...

  • An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a1[7] given the declaration int a[4][5])