我无法理解这种类型的铸造

时间:2012-08-05 07:02:38

标签: c arrays pointers type-conversion

我已经使用intchar进行了类型转换,但没有指针,所以我发布了这个问题。

#include <stdio.h>
int main() {
    int a[4] = { 1, 2, 6, 4 };
    char *p;
    p = (char *)a;   // what does this statement mean?
    printf("%d\n",*p);
    p = p + 1;        
    printf("%d",*p);  // after incrementing it gives 0 why?
}

printf的第一次调用给出了数组的第一个元素。在p=p+1之后,它会0。为什么呢?

6 个答案:

答案 0 :(得分:5)

让我们设想一个相当典型的平台,其中一个字节是8位,内存使用小端字节排序排列,而int表示内存中的四个字节。在此平台上,1的值将如此布局:

00000001 00000000 00000000 00000000
^
the first element of 'a'

p被声明为指向char(不是int)的指针,并被初始化为指向数组a的第一个元素。此平台上的char表示一个字节。上面解释为int的{​​{1}}值看起来像这样:

char

因此,无论我们读取一个字节还是四个字节,即我们是读取00000001 -------- -------- -------- | | ------ char is only 8 bits wide 还是*p,值都是a[0]。但是,当您递增1,指向p的指针时,它现在指向内存中的下一个 char ,这是下一个字节:

char

00000001 00000000 00000000 00000000 00000001 00000000 -------- -------- ^ ^ ^ ^ p p+1 p+2 p+3 ... 指向下一个a[1]int),2指向下一个p[1],即char


另外,您实际上偶然发现了一种确定给定处理器是使用小端还是大端字节顺序的方法。如果系统是big-endian(最重要的字节优先),那么你的第一个0将打印0.这是因为内存布局会发生变化:

printf

如果您有多个以big-endian顺序排列的字节,表示值1,并且您只读取第一个字节,则可以使用其值(0000000 00000000 00000000 00000001 ^ the first element of 'a' 0000000 -------- -------- -------- ^ p 1)来测试机器的字节顺序:

0

答案 1 :(得分:2)

确切地说,第一个printf没有给出数组的第一个元素,它给第一个元素的第一个 8位,恰好等于第一个元素数值。 第二个printf给出第一个元素的下一个8位,在这种情况下为0。

1 = 00000000 00000000 00000000 00000001(32位)

答案 2 :(得分:2)

你有一个包含四个整数的数组。您尝试将它们作为字符的“数组”进行访问。这就是演员的意思。

对于第二个printf打印零,请记住整数是四个字节,而字符只有一个。因此,增加指针p将使p指向第一个整数的第二个字节,即零。如果你有一个更大的数字(即超过255),那么第二个字节也会有一个值。但请注意,这仅适用于 big endian 上的 little endian 的Intel类型计算机,{em}大端计算机上printf将打印为零。

答案 3 :(得分:1)

int a[4] = { 1, 2, 6, 4 };

声明一个as数组。此时a存储数组第一个元素的地址。

char *p;

将p声明为pointercharacter

p = (char *)a;

现在p&amp; a都存储地址。因此,存储在a(数组第一个元素的address)的地址被分配给p。类型转换是在p声明为char *

时完成的

它的作用是,假设存储在a的地址为100 并假设int占用2个字节且char占用内存中的1个字节

a+1 would return a+size of int(2) = 102

p+1 would return p+size of char(1) = 101 

这将把输出解释为

一个。存储在a的两个字节包含数组的第一个元素。

B中。存储在p的一个字节是整数1的第一个字节的字符表示,即0

希望这有帮助。

答案 4 :(得分:0)

如果使用类似处理器的英特尔,则使用小端格式存储堆栈上的字节。更多,类型int(在您的计算机上)可能有4个字节大小而char是1个字节长(您可以使用c运算符'sizeof'来验证这一点),因此整数数组的第一个元素是:

0x04 0x00 0x00 0x00

因此,当您使用char指针查看整数数组的值时,您会在时间(而非4)前进一个字节,并获得您获得的明显结果。

我希望这有帮助!

答案 5 :(得分:0)

a是指向内存数组的指针。该存储器可能以小端二进制补码格式排列为16字节的连续块。

当你施放它时,你基本上只是说“好吧,我知道这是一个指向一组int的指针,但现在我们将把数据重新解释为一个字符数组”。 char通常是一个字节。因此,当您向指针添加一个时,会增加指向指针的位置。因为它是一个char数组,所以它在数组中向前推进了一个 byte ,该数组位于int的中间,包含0。

根据我对您计算机架构的假设来澄清

  

小端数(最低有效字节优先):
  二进制中的00000001000000000000000000000000 =十进制中的1   二进制000000100000000000000000000000000 =十进制2   二进制中的00000110000000000000000000000000 =十进制中的6   二进制中的00000100000000000000000000000000 =十进制中的4

您的整数数组如下所示:

  

00000001000000000000000000000000000000100000000000000000000000000000011000000000000000000000000000000100000000000000000000000000

变量“a”指向第一个整数,即32位(即“* a”是00000001000000000000000000000000)。如果向变量“a”添加一个,则递增指针,因此*(a + 1)指向第二个int 00000010000000000000000000000000)。

现在,您将变量“a”强制转换为“char *”指针。所以,现在,变量“p”指向同一个地方,但因为它是一个char指针,指向第一个char的指针,即8位(即“* p”是00000001,第一个字节你的阵列。)

最后,当你增加“p”时,你增加指针。因为“p”是指向字符的指针,所以它会前进一个字节,因此“*(p + 1)”为00000000