C指针类型转换

3
#include <stdio.h>
int main(void)
 {
  char *cp;
  short *sp;
  int *ip;
  short x[6];
  int i, y;
  y = 0x0102;
  for (i = 0; i < 6; i++) 
  {
    x[i] = y;
    y = y + 0x1010;
  }
  cp = (char*) x;
  printf("1) *cp = %x\n", *cp);
  sp = x;
  printf("2) *sp = %x\n", *sp);
  printf("3) cp[3] = %x\n", cp[3]);
  ip = (int*) x;
  ip = ip + 1;
  printf("A) *ip = %x\n", *ip);
  printf("B) cp[6] = %x\n", cp[6]);
  sp = sp + 5;
  printf("C) *sp = %x\n", *sp);
  *x = *cp + 2;
  printf("D) cp[1] = %x\n", cp[1]);
  return 0;
}

我不理解如何将短数组强制类型转换为 char,以及在类型转换发生时会发生什么。是否有人可以帮我解决这个问题!

不是将数组转换,而是指针。 x 是第 0 个元素的地址,基本上它是 short* - zerkms
4
这种行为是未定义的,因为程序通过指向“int”的指针访问了一个“short”对象,所以任何事情都有可能发生。 - n. m.
2
除了无效的强制类型转换外,"%x"对于大多数值来说都是错误的格式。 - Bo Persson
%x 用于以十六进制格式打印输出。 - Sinduja Prakash
这个程序会产生一个输出,但我不知道这个输出是如何得到的... - Sinduja Prakash
2
@SindujaPrakash 你似乎误解了Bo的意思。请阅读printf文档中有关格式说明符期望的具体信息。你会发现%x期望一个“无符号整数”,而你实际上是在向printf传递char值,这样做实际上是在欺骗它。唯一能拯救你的运行时错误的是默认参数提升,它将这些值提升为“int”,虽然仍然是错误的,但至少大小兼容。 - WhozCraig
1个回答

7
你声明了一个名为 x 的 6 个元素的 short 数组。
你给每个元素赋了值。初始值如下:
+------+--------+
| x[0] | 0x0102 |           
+------+--------+
| x[1] | 0x1112 |             
+------+--------+             
| x[2] | 0x2122 |             
+------+--------+             
| x[3] | 0x3132 |             
+------+--------+             
| x[4] | 0x4142 |             
+------+--------+             
| x[5] | 0x5152 |             
+------+--------+

我在这里做了一些假设,但如果不是你的情况,请进行修改。

sizeof(char)  = 1 bytes
sizeof(short) = 2 bytes
sizeof(int)   = 4 bytes
Endianness    = little endian

因此在内存中,它看起来像这样:
+----+----+----+----+----+----+----+----+----+----+----+----+
| 11 | 10 | 9  | 8  | 7  | 6  | 5  | 4  | 3  | 2  | 1  | 0  |
+----+----+----+----+----+----+----+----+----+----+----+----+
| 51 | 52 | 41 | 42 | 31 | 32 | 21 | 22 | 11 | 12 | 01 | 02 |
+----+----+----+----+----+----+----+----+----+----+----+----+
| x[5]    | x[4]    | x[3]    | x[2]    | x[1]    | x[0]    |
+---------+---------+---------+---------+---------+---------+
  • 第一行:字节编号(仅用于标识目的)
  • 第二行:内存中内容的十六进制表示(每两个十六进制字符代表一个字节)
  • 第三行:数组x的索引

您将x的基地址转换为char指针cp并将其赋值。 printf()看到了在*x中大小为1字节的字符。

x指向字节0,cp也是如此,但对于后者,只有1字节被考虑,因为sizeof(char)1

字节0处的内容恰好为0x02

所以,

cp = (char*) x;
printf("1) *cp = %x\n", *cp);

打印输出2

sp是一个short指针,与x相同类型。所以*sp会打印与*x相同的内容。它将从给定地址开始考虑前2个字节。sp指向字节0。因此,将考虑字节01。因此,值为0x0102,由之前提到的代码打印出来。

sp = x;
printf("2) *sp = %x\n", *sp);

cp仍然指向字节0cp[3]等效于*(cp+3)。由于cp是一个char指针,cp+3将指向0 + 3*sizeof(char),即0 + 3*1,这又是字节3

在字节3处,我们有0x11,因为sizeof(char)1,所以只考虑单个字节。

因此,

printf("3) cp[3] = %x\n", cp[3]);

将打印11

ip = (int*) x;
ip = ip + 1;
printf("A) *ip = %x\n", *ip);

整数指针ip被分配到x的基地址。然后,ip增加了1。最初,ip指向字节0。由于ip+1将指向字节0 + 1*sizeof(int),即0 + 1*4,这又是字节4。
因此,ip现在指向字节4。由于它是一个整数指针,因此会考虑4个字节-即字节4、5、6和7,其内容为31322122cp[6]表示*(cp+6)cp+6指向字节6,其内容为32
因此,
printf("B) cp[6] = %x\n", cp[6]);

打印输出32

sp = sp + 5;
printf("C) *sp = %x\n", *sp);

sp在加上5之后,现在指向字节0 + 5*sizeof(short),也就是0 + 5*2,即字节10,而在考虑2个字节(字节10和11)的内容后,它的内容为5152

*x = *cp + 2;

*cp的值为0x02。 *cp + 2的值是0x02 + 0x02 = 0x04 = 0x0004。 这个值被赋给了由*x指向的整数(字节0和1)。
因此,字节0现在是0x04,字节1现在是0x00。
cp[1]就是*(cp+1)。cp+1指向字节1,内容现在为0x00,这将在输出时打印出来。
printf("D) cp[1] = %x\n", cp[1]);

完成了。

1
非常感谢。这是一个完美的解释,我理解得很好。 - Sinduja Prakash
@SindujaPrakash 很高兴能帮忙。 - J...S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接