将指针强制转换为char指针会导致C中的数据丢失?
我有以下代码:
#include #include 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
。 我可能理解为什么,但我不确定。 请问有人给我一个明确的解释吗?
非常感谢。
int
260(= 256 * 1 + 4)在内存中看起来像这样 – 注意这取决于机器的字节顺序 – 这也适用于32位(4字节) int
:
0x04 0x01 0x00 0x00
通过使用char
指针,您指向第一个字节并将其更改为0x00
,这会将int更改为256(= 256 * 1 + 0)。
你显然是在使用小端机器。 发生的事情是你从一个占用至少两个字节的int开始。 值260是256 + 4。 256进入第二个字节,第4个进入第一个字节。 当您将0写入第一个字节时,您只剩下第二个字节中的256个。
在C中,指针根据与指针关联的类型引用字节块。 因此,在您的情况下,整数指针指的是大小为4个字节的块,而char只有一个字节长。 当您将char设置为0时,它只会更改整数值的第一个字节,但由于数字在现代机器的内存中的存储方式(实际上与编写它的方式相反),您将覆盖最低有效字节(这是4)你剩下w / 256作为值
我理解改变价值究竟发生了什么:
#include #include 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
所以基本上问题不在于你有数据丢失,是char指针只指向int的第一个字节,所以它只改变了,其他字节没有改变,这就是为什么那些奇怪的值(如果你在INTEL处理器的第一个字节是最不重要的,这就是你改变数字“最小”部分的原因
你的问题是作业* pp = 0; 您正在取消引用指向n的pp,并更改n。 但是,pp是一个char指针,所以它不会改变所有n,这是一个int。 这导致其他答案中的二元并发症。
就C语言而言,您正在做的描述是修改 int
变量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
,它将保证可以工作(尽管这些位的排序仍然依赖于实现)。
考虑到32位系统, 256
将像这样表示。
00000000 (Byte-3) 00000000 (Byte-2) 00000001(Byte-1) 00000100(Byte-0)
现在当p
被类型转换为char指针时,指针上的标签会改变,但内存内容不会改变。 这意味着早期的p
可以访问4个字节,因为它是一个整数指针,但现在它只能访问1个字节,因为它是一个char指针。 因此,只有LSB变为零,而不是所有4个字节。
它变成了
00000000 (Byte-3) 00000000 (Byte-2) 00000001(Byte-1) 00000000(Byte-0)
因此,o / p是256
。