C++ 将双精度位模式显示为十六进制?

C++ 将双精度位模式显示为十六进制?,c++,c,floating-point,double,type-punning,C++,C,Floating Point,Double,Type Punning,我试图使用printf在控制台上打印double的二进制表示。以下是我目前掌握的代码: #include <stdio.h> int main() { double a = 4.75; unsigned long long b = *(unsigned long long *) &a; printf("Double a = %f (0x%x)" a, b); } 我很确定,因为我的系统是little endian,所以它只捕获前32位,而前32位都

我试图使用
printf
在控制台上打印double的二进制表示。以下是我目前掌握的代码:

#include <stdio.h>

int main()
{
    double a = 4.75;
    unsigned long long b = *(unsigned long long *) &a;
    printf("Double a = %f (0x%x)" a, b);
}
我很确定,因为我的系统是little endian,所以它只捕获前32位,而前32位都是零。然而,我不知道如何解决这个问题

我想这可能是因为linux中long是64位的,但经过测试,我又得到了同样的结果。也许我打印不正确?不确定,请告诉我,谢谢您的时间。

在C语言中,代码类似

unsigned long long b = *(unsigned long long *) &a;
是非法的,因为它违反了一个称为“严格别名”的规则,该规则涉及一种类型的指针引用另一种类型的对象

但是,有一个例外:字符指针可以别名任何对象

因此,使用char指针,您可以在C中执行如下操作:

#include <stdio.h>

int main()
{
    double a = 4.75;
    unsigned char* p;

    // Method 1 - direct memory read
    p = (unsigned char*)&a;
    for (size_t i=0; i < sizeof(double); ++i)
    {
        printf("%02x ", *p);
        ++p;
    }
    printf("\n");

    // Method 2 - reversed memory read
    size_t i = sizeof(double);
    p = (unsigned char*)&a + i - 1;
    do
    {
        printf("%02x ", *p);
        --p;
        --i;
    } while(i > 0);

    return 0;
}
这两种方法打印的endianness不同

如果你不喜欢指针,你可以选择使用一个联合。比如:

#include <stdio.h>

int main()
{
    union
    {
        double a;
        char c[sizeof(double)];
    } d;
    d.a = 4.75;

    for (size_t i=0; i < sizeof(double); ++i)
    {
        printf("%02x ", d.c[i]);
    }
    printf("\n");

    size_t i = sizeof(double);
    do
    {
        --i;
        printf("%02x ", d.c[i]);
    }
    while (i > 0);
    printf("\n");


    return 0;
}

您的代码有两个问题,一个简单的问题是您使用了错误的格式说明符
%llx
是无符号long的正确说明符。clang和gcc都使用
-Wall
,为此提供了警告

第二个问题是您违反了以下规则:

键入pun(在C和C++中)的正确方法是使用memcpy():

在C++20中的上述注释中的严格别名链接中,我们应该得到
位转换
,这将简化类型双关,例如:

b = bit_cast<unsigned long long>(a);
b=位转换(a);
在C++中:

double a = 4.75;
char tmp[sizeof(double)];
memcpy(tmp, &a, sizeof(double));
... // print individual bytes as hex
或者:

double a = 4.75;
unsigned char* tmp = reinterpret_cast<unsigned char*>(&a);
for (int i = 0; i < sizeof(double); i++)
  ... // print *(tmp + i) as hex
双a=4.75;
无符号字符*tmp=重新解释强制转换(&a);
对于(int i=0;i
*(无符号长*)&a违反严格别名?@SouravGhosh是,请参阅
printf(“双a=%f(0x%llx)”,a,b)@SouravGhosh该信息是为可能不理解的普通观众提供的;-)我真的不明白这不是一个严格的别名问题。如果我们要保持开放,问题需要缩小到C或C++。目前它太宽了。如果有高质量的用户使用黄金徽章,在编写答案之前,可以调整C++和C++标签的交叉张贴方面的努力。你的答案是C。希望OP注意到了这一点。
unsigned long long b = *(unsigned long long *) &a;
std::memcpy( &b, &a, sizeof(double));
b = bit_cast<unsigned long long>(a);
double a = 4.75;
char tmp[sizeof(double)];
memcpy(tmp, &a, sizeof(double));
... // print individual bytes as hex
double a = 4.75;
unsigned char* tmp = reinterpret_cast<unsigned char*>(&a);
for (int i = 0; i < sizeof(double); i++)
  ... // print *(tmp + i) as hex