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?当它的地址递增,然后取消引用时,它会得到正确的十六进制值。为什么?由于别

我正在努力理解C,我遇到了这个例子:

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
<