int main()
{
int x[] = {1, 2, 3};
char *p = &x;
printf("%d", *(p+1));
return 0;
}
我在codeblocks中运行代码,并将0作为输出。 如果我将p改为int指针,那么它将2作为输出。
int main()
{
int x[] = {1, 2, 3};
int *p = &x;
printf("%d", *(p+1));
return 0;
}
为什么会这样?
答案 0 :(得分:4)
当p
被声明为指向char
的指针时,它应指向大小为1
字节的数据。因此(p + 1)
将p
增加1个字节。
由于int
长度至少为4个字节,(p + 1)
可能指向1
的高阶字节中的第二个,仍为0
。< / p>
如果您希望它具有相同的输出,您可以执行类似的操作
printf("%d\n", *(p + sizeof(int)));
但最好避免使用-Wall
标记来避免此类代码,这肯定会在您的情况下产生警告。
答案 1 :(得分:2)
当你增加一个指针时,它会移动它所指向的东西的大小。
假设您有16位整数。在二进制中,第一个是:0000 0000 0000 0001
char指针一次只能指向8位:0000 0000
答案 2 :(得分:2)
要从稍微不同的角度看一下,关于二元+
运算符,章节6.5.6,C99
标准的第8段说,[强调我的]
当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则 结果指向偏离原始元素的元素,以便生成和原始数组的下标的差异元素等于整数表达式 。换句话说,如果表达式P指向数组对象的第i个元素,则表达式(P)+ N(等效地,N +(P))和 (P)-N(其中N具有值n)分别指向数组对象的第i + n和第i-n个元素,只要它们存在。
因此,在第一种情况中,p
的类型为char *
,(p + 1)
将结果作为指针递增{{1} } [表示1个字节,大多数的情况],因此指向sizeof(char)
所持有的 char数组的第2个元素。实际上,p
所拥有的数组的类型为p
[在32位系统中假设长度为4个字节],因此根据存储的值,[{{1} {}保存为int
},1
打印出0000 0000 0000 0001
。
OTOH,在第二种情况中,*(p+1)
的类型为0
,p
将结果作为指针递增{{1}因此指向int *
持有的 int数组的第二个元素。实际上,由(p + 1)
保存的数组属于sizeof(int)
类型,因此根据存储的值[p
],p
打印出int
。
答案 3 :(得分:2)
假设sizeof(int)是16位。二进制2是00000000 00000010。 sizeof(char)是8位。 小端和大端是存储多字节数据类型的两种方式。
请考虑以下代码:
int i = 2;
char c =(char )&amp; i;
if((* c)== 2)
printf(&#34; Little endian&#34;);
否则//如果* c为0
printf(&#34; Big endian&#34;);
从这段代码可以得出结论,Big Endian会将2存储为00000000 00000010.但Little Endian会将其存储为00000010 00000000.,因此输出为零意味着前8位为零,因此系统为Big Endian。如果它一直在使用Little Endian,那么答案将是2,因为char p应该仅指向8位。 实际上,声明指针的数据类型意味着指定您希望它引用的位数以及递增时将跳转的位数。 如果在此示例中,因为p是char指针,*(p + 1)将引用Big endian中的00000010和Little Endian中的00000000。 你的编译器可能正在使用32位进行整数,所以我认为在两种情况下*(p + 1)都会给出0.(因为2 =&gt; 00000000 00000000 00000000 00000010来自任何一方的第二个字节为0)
参考:`#include
int main()
{
int x[] = {1, 2, 3};
char *p = &x;
printf("%d\n", *p);
printf("%d\n", *(p+1));
printf("%d\n", *(p+2));
printf("%d\n", *(p+3));
printf("%d\n", *(p+4));
printf("%d\n", *(p+5));
printf("%d\n", *(p+6));
printf("%d\n", *(p+7));
printf("%d\n", *(p+8));
return 0;
}`
输出: 1 0 0 0 2 0 0 3