Typecasting指向整数指针的字符指针

时间:2016-06-22 16:47:04

标签: c pointers

#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? 如果我想跳过这么多字节,那么我应该指出那么多字节的指针吗?

4 个答案:

答案 0 :(得分:2)

p=(int *)(p+1);约束违规,因为int *可能未分配给char *

编译器必须发出诊断消息。具有约束违规的程序生成的任何可执行文件的行为都是未定义的。

答案 1 :(得分:0)

这是关于intchar 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)。

最后,假设pchar*,代码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