Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将int指针转换为char指针会导致C中的数据丢失?_C_Pointers - Fatal编程技术网

将int指针转换为char指针会导致C中的数据丢失?

将int指针转换为char指针会导致C中的数据丢失?,c,pointers,C,Pointers,我有以下代码: #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; } #包括 #包括 int main(int argc

我有以下代码:

#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;
}
#包括
#包括
int main(int argc,char*argv[])
{
int n=260;
int*p=&n;
char*pp=(char*)p;
*pp=0;
printf(“n=%d\n”,n);
系统(“暂停”);
返回0;
}
程序的输出put为
n=256
。 我可能理解这是为什么,但我不是很确定。 谁能给我一个清楚的解释吗

非常感谢。

内存中的
int
260(=256*1+4)将类似于此-请注意,这取决于机器的大小-同样,这是一个32位(4字节)的
int

0x04 0x01 0x00 0x00

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

您显然是在一台小型endian机器上工作。发生的事情是,您从一个至少占用两个字节的int开始。值260是256+4。256在第二个字节中,4在第一个字节中。当您将0写入第一个字节时,第二个字节中只剩下256个。

通过更改值,我了解了具体情况:

#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;
}
#包括
#包括
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);
系统(“暂停”);
返回0;
}
输出值为 20 和 276


所以基本上问题不在于数据丢失,而是char指针只指向int的第一个字节,所以它只会改变,其他字节不会改变,这就是为什么这些奇怪的值(如果你在英特尔处理器上,第一个字节是最不重要的,这就是为什么你要改变“最小的”C中数字的一部分指针根据与指针相关联的类型引用一个字节块。因此,在您的例子中,整数指针引用一个大小为4字节的块,而字符只有一个字节长。当您将字符设置为0时,它只会更改整数值的第一个字节,但这是因为数字是如何存储在内存中的y在现代机器上(实际上与您的写入顺序相反),您正在覆盖最低有效字节(即4),剩下的值为w/256

您的问题是赋值 *pp=0; 您正在解引用指向n的pp,并更改n。 然而,pp是一个字符指针,所以它不会改变所有的n
在C语言中,您所做的描述是修改
int
变量
n
的表示形式。在C语言中,所有类型的“表示形式”都是一个或多个字节(
无符号字符
),并且通过将指针投射到
char*
unsigned char*
来访问底层表示是合法的-后者更好,因为如果我在这里讨论的话,可能会不必要地使事情复杂化

正如schnaader所回答的,在一个小的endian上,用32位
int
补码实现,260的表示是:

0x04 0x01 0x00 0x00
0
覆盖第一个字节会产生:

0x00 0x01 0x00 0x00
这是256在这种实现上的表示


C允许具有填充位和陷阱表示的实现(如果被访问,会发出信号/中止程序),因此,一般来说,以这种方式覆盖部分而不是全部
int
是不安全的。尽管如此,它在大多数现实世界的机器上都能工作,如果您改用类型
uint32\u t
,它将保证工作(尽管位的顺序仍然取决于实现)考虑到32位系统,
256
将以如下方式表示

00000000 (Byte-3)   00000000 (Byte-2)    00000001(Byte-1)     00000100(Byte-0)
现在当
p
被键入字符指针时,指针上的标签会改变,但内存内容不会改变。这意味着以前的
p
可以访问4个字节,因为它是整数指针,但现在它只能访问1个字节,因为它是字符指针。因此,只有LSB会将更改为零,而不是所有的4个字节

它变成了

00000000 (Byte-3)   00000000 (Byte-2)    00000001(Byte-1)     00000000(Byte-0)
因此,o/p为
256