将字符指针强制转换为整型指针

5
我看到了一些关于如何找到计算机体系结构的字节序的例子。假设我们有一个指向int数据类型的整数指针。假设int值为0x010A0B12。在小端架构中,最不重要的字节,即12,将存储在最低的内存地址中,对吧?因此,在4字节整数中,最低位字节将为12。
现在,进行检查。如果我们声明一个char指针p,并将整数指针强制转换为char *并将其存储在p中,然后打印p的解引用值,我们将获得有关计算机体系结构字节序的线索。如果它是12,则表示小端;01表示大端。听起来真的很方便...
int a = 0x010A0B12;
int *i = &a;
char *p = (char*)i; 
printf("%d",*p); // prints the decimal equivalent of 12h!

这里有几个问题。由于指针是强类型的,那么字符指针是否应该严格指向char数据类型?另外,使用%d打印有什么问题吗?难道我们不应该使用%c来打印字符吗?


2个回答

7
由于指针是强类型的,那么字符指针是否应该严格指向char数据类型呢?
在C语言中,任何指针都可以安全地转换为char*和void*。因此,将int*转换为char*是允许的,并且也是可移植的。指针将指向您的int内部表示的初始字节。
难道我们不应该使用%c来打印字符吗?
这里还有另一件事情:printf的可变长度参数列表。当您将char传递给printf的未类型化参数时,默认转换适用:char转换为int。这就是为什么%d格式可以很好地接受数字并按照您的期望打印出来的原因。
您也可以使用%c。处理%c指定符的代码读取参数作为int,然后将其转换为char。0x12是一个特殊字符,所以您看不到统一的打印输出。

谢谢,虽然,你所说的“printf的未类型化参数”是什么? - nirvanaswap
@nirvanaswap 在 print 函数的签名末尾加上三个点 ...,即 int printf ( const char * format, ... ),表示您可以传递任何类型的其他参数。 - Sergey Kalinichenko

-1
由于指针是强类型的,那么字符指针严格来说应该只指向char数据类型,这种行为有点未定义,但大多数合理的实现会按照你的意思去做。所以大多数人会认为这是可以的。
使用%d打印有什么问题吗?格式化符号%d期望int类型的参数,而实际的char类型的参数会被C语言的规则提升为int类型,所以这也是可以的。你可能不想使用%c,因为p指向的字节内容可能是任何字节,不一定是有效的文本字符。

1
我正在取消引用,那么很明显%p不是我要找的东西,对吗? - nirvanaswap
@nirvanaswap:是的,抱歉,我已经编辑过了。对于dasblinkenlight:存在未定义行为,假设内存中的任何字节都可以单独寻址和访问。通常情况下这是正确的,但是想象一下,如果OP试图访问32位硬件寄存器中的中间字节,而该寄存器只能作为整个32位读取,并且只能在对齐地址处读取,那么它将导致运行时异常。 - ddbug
这是非常错误的。通过 char * 地址访问对象内存始终是有效的;最基本的 memcpy 实现都是这样做的。 - Hello71
如果编译器认可,C程序可以访问任何指针,但硬件有权出现异常。 - ddbug

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