将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