C 分配给指针时,转换地址的类型是什么?
我正在努力理解C,我遇到了这个例子:C 分配给指针时,转换地址的类型是什么?,c,pointers,casting,C,Pointers,Casting,我正在努力理解C,我遇到了这个例子: int main() { double d = 010; unsigned *pi = (unsigned *) &d; printf("%x", *++pi); } 因此,d在十进制数字系统中的值为8,1000000010。。。二进制和40200000十六进制。我不明白这个地址的类型是什么。为什么*pi不获取十六进制值,而是打印0?当它的地址递增,然后取消引用时,它会得到正确的十六进制值。为什么?由于别
int main()
{
double d = 010;
unsigned *pi = (unsigned *) &d;
printf("%x", *++pi);
}
因此,
d
在十进制数字系统中的值为8,1000000010。。。二进制和40200000十六进制。我不明白这个地址的类型是什么。为什么*pi
不获取十六进制值,而是打印0?当它的地址递增,然后取消引用时,它会得到正确的十六进制值。为什么?由于别名规则,代码实际上具有未定义的行为:您正在使用指向另一种非字符类型的类型的指针访问double
变量的表示形式
其目的是打印double
变量字节4到7中的32位,这些字节都是0
,这是因为8.0
在您的体系结构上的表示方式
强制转换告诉编译器将指针转换为另一种类型的指针。这通常不会更改其值,但取消引用结果指针可能会产生未定义的行为,字符类型除外
这是一个可移植的修改版本,可打印字节值:
#include <stdio.h>
int main() {
double d = 010;
unsigned char *p = (unsigned char*)&d;
int n = sizeof(double);
while (n --> 0) {
printf("%02x ", *p++);
}
printf("\n");
return 0;
}
#包括
int main(){
双d=010;
无符号字符*p=(无符号字符*)&d;
int n=sizeof(双精度);
而(n-->0){
printf(“%02x”,*p++);
}
printf(“\n”);
返回0;
}
英特尔Mac(little endian)上的输出:0020 40
big-endian系统上的输出:
40 20 00 00
由于别名规则,代码实际上具有未定义的行为:您正在使用指向另一种非字符类型的指针访问double
变量的表示形式
其目的是打印double
变量字节4到7中的32位,这些字节都是0
,这是因为8.0
在您的体系结构上的表示方式
强制转换告诉编译器将指针转换为另一种类型的指针。这通常不会更改其值,但取消引用结果指针可能会产生未定义的行为,字符类型除外
这是一个可移植的修改版本,可打印字节值:
#include <stdio.h>
int main() {
double d = 010;
unsigned char *p = (unsigned char*)&d;
int n = sizeof(double);
while (n --> 0) {
printf("%02x ", *p++);
}
printf("\n");
return 0;
}
#包括
int main(){
双d=010;
无符号字符*p=(无符号字符*)&d;
int n=sizeof(双精度);
而(n-->0){
printf(“%02x”,*p++);
}
printf(“\n”);
返回0;
}
英特尔Mac(little endian)上的输出:0020 40
big-endian系统上的输出:
40200000
您希望得到什么输出?此代码输出40200000,我理解这个数字,但它让我困惑了为什么地址必须递增。可能是此代码的dup,或者它可以是具有endian的东西(unsigned*)&d
是未定义的行为。这些类型不兼容,通过错误的类型取消引用值是一种严格的别名冲突。通常,C中的强制转换根本不能保证是安全的和可预测的。尽可能避免它们。您希望得到什么样的输出?这段代码打印出40200000,我理解这个数字,但它让我困惑了为什么地址必须递增。可能是这段代码的dup,或者它可以是endianess(unsigned*)&d
是未定义的行为。这些类型不兼容,通过错误的类型取消引用值是一种严格的别名冲突。通常,C中的强制转换根本不能保证是安全的和可预测的。尽可能避免这些问题。我正要自己写一个答案,但这基本上就是我要写的。我很确定我知道现在发生了什么。所以p
指向00,假设它是LE,并且它以4计,因为这是无符号整数的大小。当你增加它时,它只会转到下一个地址并检查其他4个字节。要更便宜,格式应该是%02hhhxx
@0\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuo:不必要(即使没有额外的x
)当传递给vararg函数时,比int
短的as类型将升级为int
,当值在无符号int
范围内时,可以为无符号int
格式传递int
值。C17.21.6.1将hh
描述为:指定以下d
、i
、o
、u
、x
转换说明符适用于有符号字符
或无符号字符
参数(参数将根据整数升迁进行升迁,但其值在打印之前应转换为有符号字符
或无符号字符
);[…]0 uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。如果p
具有类型char*
,则最好使用printf(“%02hhx”,*p++)
正如我所建议的,因为在某些平台上,char
值可能是负数,并且在没有hh
的情况下会产生超过2个十六进制数字。我自己正要写一个答案,但这基本上就是我要写的。我很确定我现在明白了。所以p
指向00,假设它是LE,并且它计数s乘以4,因为这是无符号整数的大小。当你增加它时,它只会转到下一个地址并检查其他4个字节。要更贵,格式应该是%02hhxx
@0\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu小于int
的as类型在传递给vararg函数时被提升为int
,而int
值在unsigned int
范围内时,可以为unsigned int
格式传递int
值。C17.21.6.1将hh
描述为:指定以下d
<