#include <stdio.h>
int main()
{
int a[3]={2,3,4};
char *p=a;
printf("%d ",*p);
p=(int *)(p+1);//What does this statement do ?
printf("%d",*p); //Will the pointer extract 2 bytes(16 bit compiler)or1?
return 0;
}
我的输出为2 0。我理解为什么第一个printf正在打印2而不理解为什么在下一个printf中为0? 如果我想跳过这么多字节,那么我应该指出那么多字节的指针吗?
答案 0 :(得分:2)
p=(int *)(p+1);
是约束违规,因为int *
可能未分配给char *
。
编译器必须发出诊断消息。具有约束违规的程序生成的任何可执行文件的行为都是未定义的。
答案 1 :(得分:0)
这是关于int
和char
s的宽度和字节顺序的问题。
如果我们假设您使用32位小端int
和8位char
s的计算机,那么它在内存中看起来像这样:
a[0] a[1] a[2]
[2 0 0 0] [3 0 0 0] [4 0 0 0]
每个打印字符的宽度为8位,每个[ ]
设置为a
中的32位条目。
p
是指向8位char
的指针。当p
设置为指向a[0]
时,它指向a
中的前8位条目,即2
。 a中的下一个8位条目是0
右侧的2
。
如果您正在使用的机器具有int
的不同宽度或布局,那么答案可能会有所不同。
更新
这是一个16位的小端int
环境
a[0] a[1] a[2]
[2 0] [3 0] [4 0]
在32位大端int
环境中
a[0] a[1] a[2]
[0 0 0 2] [0 0 0 3] [0 0 0 4]
答案 2 :(得分:0)
该代码存在很多错误。
首先,正如M.M的回答所指出的,如果不从编译器中提出诊断消息,代码甚至都不会编译。如果是这样,您的编译器配置错误或非标准。将int*
分配给char*
不是有效的分配形式(请参阅&#34;简单分配&#34; 6.5.16.1)。两者都不相反,char *p=a;
。
即使代码被重写为有效的C,例如:
int i = *((int*)(p+1));
它仍然是非常值得怀疑的代码。首先,如果这导致访问错位,代码可能会调用未定义的行为(6.3.2.3/7)。其次,这样的代码也会违反严格的指针别名,并因此也会调用未定义的行为(6.5 / 7)。
最后,假设p
是char*
,代码printf("%d",*p);
会调用未定义的行为,因为%d
不是字符指针的有效转换说明符(7.21.6.1) / 9)。
因此,在两行代码中存在完全不同形式的未定义行为的四个可能情况......令人印象深刻。
现在,如果我们假设您的特定系统没有任何未对齐访问的问题,并且您有一些不符合指针别名规则的非标准编译器......
如果是这样,在32位系统上,可以通过以下两种方式之一分配数组:
02 00 00 00 03 00 00 00 04 00 00 00 // little endian
00 00 00 02 00 00 00 03 00 00 00 04 // big endian
在这种情况下,你的第一个printf将打印2或0,具体取决于系统,因为它指向第一个字节,并打印该字节的指向内容。
如果然后将char指针递增1并以某种方式设法将指向的内容读取为32位整数,您将获得数据
00 00 00 03 // little endian
00 00 02 00 // big endian
分别等于小数值50331648(小)和512(大)。现在您希望用它来证明,或者整个算法如何有意义,我不知道。除了研究导致此代码失败的许多方法之外,从这种做法中学到的东西并不多。
答案 3 :(得分:-1)
通过使用显式转换(int*)
判断,您对行中发生的事情的期望
p=(int *)(p+1);//What does this statement do ?
被误导了。该演员表没有做任何有用的事情。它和以下一样好:
p = p+1;
如果您希望p
指向a
中的下一个号码,则需要使用:
p = (int*)p+1;
或
p = a+1;
在评论中,你问:
最后
printf
从它指向的位置提取2个字节还是1个字节?我是16位编译器吗?
printf
个语句都不会提取2个字节。
printf
声明
printf("%d ",*p);
相当于:
char c = *p; // Extract the char from p
int i = c; // Cast the char to an int
printf("%d", i); // Print the int
第一个printf
调用的输出是2
巧合 - 您的平台的副作用是一个小端系统。如果您的平台是一个大端系统,输出将是0
。