不同的行为
问题描述:
我写这篇文章的代码输出功率为这样B C D E
不同的行为
char a[5] = {'A' , 'B' , 'C' , 'D'};
char *b = a + 2;
int i = 0 ;
for(i = 0 ; i < 4 ; i ++)
{
*b = (a[i] + 1);
printf("%c",*b);
}
但是当我添加这样的参考:
char a[5] = {'A' , 'B' , 'C' , 'D'};
char *b = &a + 2;
int i = 0 ;
for(i = 0 ; i < 4 ; i ++)
{
*b = (a[i] + 1);
printf("%c",*b);
}
输出成为刚刚B
。
答
这与指针算术如何完成有关。当你给一个指针添加一个值时,它会通过该值增加指针乘以它引用的类型的大小。
在表达式a + 2
中,a
的类型为char *
,所以加2将地址增加2 * sizeof(char) == 2
个字节。
鉴于&a + 2
,&a
具有类型char (*)[5]
,即指向数组的指针5 char
。对此添加2会使地址增加2 * sizeof(char [5]) == 10
字节。这指向数组末尾的内存位置,因此解除引用会调用undefined behavior,在这种情况下会导致循环提前退出。
在第二种情况下,您也有一个无效的赋值,因为您试图将char (*)[5]
类型的值赋值为类型为char *
的值。
答
编译器应该
char a[5] = {'A' , 'B' , 'C' , 'D'};
char *b = &a + 2; // <<< compile error
int i = 0 ;
for(i = 0 ; i < 4 ; i ++)
{
*b = (a[i] + 1);
printf("%c",*b);
}
报告错误,如果你删除生成编译错误的行,输出应该是没有从你的第一段代码差异。
'&a + 2'正在添加2 *大小的数组。当然,完全启用警告的编译器会抱怨。节省时间,启用编译器警告。 – chux
这应该产生一个编译器警告。如果没有,你需要提醒你的警告,并*修复*(不掩盖)所提到的问题。在这种情况下,它是一个指针算术的东西。 '&a'是'char(*)[5]',而不是'char *',所以表达式'a + 2'自然会产生与'&a + 2'不同的结果。给伤口加盐,后者也引起*未定义的行为*。 – WhozCraig
感谢您的帮助 –