如果我取消引用数组并添加超出数组中可用元素的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
答案 0 :(得分:6)
TL; DR: 不知道,不能说。
详细说明,在你的代码中
printf("\n*(meatBalls+5) \t\t %d \n", *(meatBalls+5));
当您尝试访问超出限制内存时,
请注意强调访问。在这种情况下,指针算法是明确定义的(一个超过最后一个元素),尝试访问导致UB的原因。
引用C11
,章节§6.5.6(强调我的)
[...]如果表达式
P
指向最后一个 数组对象的元素,表达式(P)+1
指向一个超过最后一个元素的元素 数组对象,如果表达式Q
指向一个数组对象的最后一个元素, 表达式(Q)-1
指向数组对象的最后一个元素。 如果两个指针都有 操作数和结果指向同一个数组对象的元素,或者指向最后一个数组对象的元素 数组对象的元素,评估不应产生溢出; 否则, 行为未定义。 如果结果指向一个超过数组对象的最后一个元素的那个,那么 不得用作被评估的一元*
运算符的操作数。
也就是说,%p
期望其参数为void*
,并且由于printf()
是一个可变参数函数,因此不会进行默认参数提升。因此,您需要将所有参数都转换为%p
到(void *)
答案 1 :(得分:2)
访问数组边界之外的元素是未定义的行为;所以你可以获得任何价值,但你的程序也可能崩溃。以下是C standard定义未定义行为的方式:
3.4.3未定义的行为
行为,在使用不可移植或错误的程序结构或错误数据时,为此 国际标准没有要求。
注意:可能未定义 行为的范围从完全忽略情况 不可预知的结果,在翻译或程序期间表现 以文件化的方式执行环境特征 (有或没有发出诊断信息),终止 翻译或执行(发布诊断 消息)。
这就是标准定义您的访问是未定义行为的地方:
J.2未定义的行为
1在以下情况下,行为未定义:
...
- 数组下标超出范围,即使某个对象显然也是如此 可以使用给定的下标访问(如左值表达式) a 1 [7]给出a [4] [5]中的声明)