在C语言中,将int指针转换为char指针会导致数据丢失?

4
我有以下这段代码:

我有以下这段代码:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
  int n = 260; 
  int *p = &n;
  char *pp = (char*)p;
  *pp = 0;

  printf("n = %d\n", n);
  system("PAUSE");  
  return 0;
}

程序的输出是 n = 256。 我可能知道为什么,但我不是很确定。 有人能给我一个清晰的解释吗?
非常感谢。
7个回答

11

在内存中,int类型的260(=256*1+4)看起来像这样 - 注意这取决于机器的字节序 - 同时,这是针对32位(4字节)的int

0x04 0x01 0x00 0x00

通过使用char指针,您指向第一个字节并将其更改为0x00,这将使int变为256(= 256 * 1 + 0)。


3

看起来你正在使用小端字节序的计算机。发生的情况是你开始使用至少占据两个字节的整数。数值260等于256+4。256写入第二个字节,4写入第一个字节。当你将第一个字节写入0时,第二个字节只剩下256。


1

我明白改变值会发生什么:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int n = 260; 
  int *p = &n;
  char *pp = (char*)p;
  *pp = 20;

    printf("pp = %d\n", (int)*pp);
  printf("n = %d\n", (int)n);
  system("PAUSE");  
  return 0;
}

输出值为 20 和 276

所以基本上问题不是数据丢失,而是字符指针仅指向 int 的第一个字节,因此仅更改该字节,其他字节未更改,这就是为什么会出现奇怪的值(如果您在 INTEL 处理器上,则第一个字节是最不重要的,这就是为什么更改数字的“最小”部分的原因)。


1
在C语言中,指针根据与指针相关联的类型引用一块字节块。因此,在您的情况下,整数指针引用大小为4个字节的块,而char只有一个字节长。当您将char设置为0时,它仅更改整数值的第一个字节,但由于现代计算机上数字存储的方式(实际上是与您编写的方式相反),您正在覆盖最不重要的字节(原来是4),所以留下了256作为值。

0
关于 C 语言,你所做的事情是修改变量 n 的表示方式。在 C 中,所有类型都有一个“表示方式”,由一个或多个字节(unsigned char)组成,并且可以通过将指针强制转换为 char * 或 unsigned char * 来访问底层表示——后者出于一些不必要地复杂化问题的原因而更好。
正如 schnaader 所回答的,在一个带有 32 位 int 的小端二进制补码实现中,260 的表示形式是:
0x04 0x01 0x00 0x00

将第一个字节覆盖为0,结果如下:

0x00 0x01 0x00 0x00

这是在这种实现中表示256的方式。

C允许具有填充位和陷阱表示(如果访问它们会引发信号/中止程序)的实现,因此通常以这种方式部分但不全部地覆盖int是不安全的。尽管如此,在大多数真实世界的机器上它确实有效,如果您改用uint32_t类型,则可以保证其有效(尽管位的排序仍取决于实现)。


0
你的问题在于赋值语句 *pp = 0; 你对指向n的指针pp进行了解引用并修改了n的值。 然而,pp是一个字符型指针,所以它不能改变所有的n,因为n是整型的。 这就导致了其他答案中的二进制复杂性问题。

0

考虑到32位系统,256将会被表示为这样。

00000000 (Byte-3)   00000000 (Byte-2)    00000001(Byte-1)     00000100(Byte-0)

现在当 p 被强制类型转换为 char 指针时,指针上的标签会改变,但内存内容不会改变。这意味着之前 p 可以访问 4 个字节,因为它是一个整数指针,但现在它只能访问 1 个字节,因为它是一个 char 指针。所以,只有最低有效位被更改为零,而不是所有 4 个字节。

并且它变成

00000000 (Byte-3)   00000000 (Byte-2)    00000001(Byte-1)     00000000(Byte-0)

因此,输出结果为256

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