我对类型指针到泛型指针以及如何通过使用类型转换特性相互作用有疑问。
我创建了两个指针:一个泛型和一个类型化。
泛型目标指向字符变量的内存位置。
Typed通过类型转换指向泛型指针。
当我想打印类型指针中的值时,我的问题就开始了。
fprintf(stdout,"Integer Adress: %p | Char Value: %c | Dead Integer Value: %i \n",integerPointer, *integerPointer, *integerPointer);
字符串
->联系地址
-> char值
但是第三个返回一个死整数值,为什么?我以为它会返回字符的ASCII值,也就是65。
以下是完整代码:
#include <stdio.h>
int main(){
char letter = 'A';
void* genericPointer = &letter;
int* integerPointer = (int*) genericPointer; // Typecasting
fprintf(stdout,"Generic Adress: %p | Char Value: %c | Integer Value: %i \n",genericPointer, *(char*) genericPointer, *(char*) genericPointer); 🟩
fprintf(stdout,"Integer Adress: %p | Char Value: %c | Integer Value: %i \n",integerPointer, *integerPointer, *(char*)integerPointer); 🟩
fprintf(stdout,"Integer Adress: %p | Char Value: %c | Dead Integer Value: %i \n",integerPointer, *integerPointer, *integerPointer); 🛑
// Why don't 65?
return 0;
}
型
输出:
Generic Adress: 0x7ffc31336a77 | Char Value: A | Integer Value: 65
Integer Adress: 0x7ffc31336a77 | Char Value: A | Integer Value: 65
Integer Adress: 0x7ffc31336a77 | Char Value: A | Dead Integer Value: 862615361
型
2条答案
按热度按时间iih3973s1#
在计算机内存中没有“未定义值”。内存总是包含一些字节,在大多数情况下,一些来自先前代码的随机数据。
现在,
char
变量的大小为1字节。您将获取该1字节的地址并将其强制为指向int
的指针。int
的大小为4字节。int
中缺少3个字节。这些字节填充了一些随机数据。这3个字节的随机数据就是为什么您会看到“死整数”,并且每次运行都不同。这里有一些图表来帮助你:
字符串
的数据
您正在解引用
integerPointer
,它指向letter
。letter
中没有足够的字节,因此使用属于some_junk
的接下来的几个字节。在我的图表中,这些字节是0x41
(从char letter
),和0x2a
,0x00
,0x00
(int some_junk
的前三个字节),所有这些,在little endian的情况下,使整数10817
。所有这些都创造了你的“死整数”。
5t7ly7z52#
你的指针实际上指向一个
char
,而不是一个int
。在大多数体系结构上,一个int
是四个字符的大小。当你将它解引用为一个int*
时,它会试图读取一个完整的int
s值的数据。在某些体系结构上,你已经完成了这里;如果地址没有正确对齐一个int
,你的程序会崩溃。在其他情况下,比如你的,它从相邻内存地址(可能是局部地址,可能是返回地址,可能是编译器生成的堆栈保护标志等)的堆栈中提取
65
* 和 * 三个字节的相邻数据。你可以看到你原来的65在那里;您的系统是little-endian,因此读取的第一个字节形成结果
int
的最低字节,可以通过执行862615361 & 0xff
屏蔽高三个字节来恢复,这会产生65
。其他三个字节,以十六进制表示,是336a77
,你首先会从char
的地址中识别出来(因为指针本身被当作相邻内存提取)。简而言之:不要这样做。这是一种未定义的行为,虽然它通常在任何给定的架构上以可预测的方式运行,但关闭优化后,它不会以一种“有用”或“可移植”的方式运行。