我编写了一些c代码来处理内存中的浮点值,但最终从带有-std=c11选项的"GCC(GCC)12.1.1 20220730"的printf编译中得到了一些意外的输出.

I have no idea why it's behaving like this and would like to know what's happening, if I'm doing something wrong and how do I get it to printf a float value as hex if it's possible without converting it to another type first?

下面是使用的代码和不同运行的输出.

代码:

#include <stdio.h>

int main()
{
    float f3 = 1.1;
    float f4 = 1.0;
    unsigned char *t1 = &f3;

    unsigned *t2 = &f3;

    printf("P1: %x\n", t2[0]);
    printf("P2: %x %x %x %x\n", t1[0], t1[1], t1[2], t1[3]);
    printf("P3: %p\n", &f3);
    printf("P4: %lx, %lx, %llx\n", &f3, f3, f4);

    printf("T1: %f, %f, %lx, %lx\n", f3, f4, f4, f3);
    printf("T2: %x, %lx\n", f4, f3);
    printf("T3: %x, %lx\n", f3, f4);
    
    return 0;
}

主要问题似乎是将浮点数打印为十六进制:

printf("%x\n", f3);

输出1:输出1:

P1: 3f8ccccd                            // as expected
P2: cd cc 8c 3f                         // as expected
P3: 0x7ffc667d4d40                      // as expected
P4: 7ffc667d4d40, 3ff19999a0000000, 0   // pointer value as expected, but second and third isn't. Values stay the same after each run

T1: 1.100000, 1.000000, 5556db09b2a0, 0 // first two values as expected, second and third isn't, Values do not stay the same after each run
T2: db09b2a0, 0                         // this value keeps changing after each run
T3: db09b2a0, 0                         // same as above, but should be different? Also changes after each run.

输出2:输出2:

P1: 3f8ccccd
P2: cd cc 8c 3f
P3: 0x7ffef87ebb00
P4: 7ffef87ebb00, 3ff19999a0000000, 0

T1: 1.100000, 1.000000, 55fb6a1962a0, 0
T2: 6a1962a0, 0
T3: 6a1962a0, 0

输出3:以下内容:

P1: 3f8ccccd
P2: cd cc 8c 3f
P3: 0x7ffdb2026640
P4: 7ffdb2026640, 3ff19999a0000000, 0

T1: 1.100000, 1.000000, 564dd210c2a0, 0
T2: d210c2a0, 0
T3: d210c2a0, 0

推荐答案

主要问题似乎是将浮点数打印为十六进制:

printf("%x\n", f3);

是的,因为%x格式说明符需要unsigned int作为参数,但您传入的是float,而float正被提升为double.

使用错误的格式说明符触发undefined behavior,在本例中显示为奇怪的输出.至于幕后发生的事情,浮点值通常使用浮点寄存器传递给函数,而整数值通常被压入堆栈.

这也是无效的:

printf("P1: %x\n", t2[0]);

因为它会导致严格的混叠违规.这基本上意味着您不能像访问另一种类型一样访问一种类型的字节,除非目标类型是charunsigned char.

打印浮点类型的字节表示的正确方法是让unsigned char *个指针指向第一个字节,然后循环遍历字节并打印每个字节.

C++相关问答推荐

如何在C中通过套接字自定义数据类型读取原始变量?

将常量转换为指针会增加.数据大小增加1000字节

当我更改编译优化时,相同的C代码以不同的方式运行

如何创建一个C程序来存储5种动物的名字,并在用户 Select 其中任何一种动物时打印内存地址?

在Linux上使用vscode和lldb调试用Makefile编译的c代码

OpenSSL:如何将吊销列表与SSL_CTX_LOAD_VERIFY_LOCATIONS一起使用?

为什么用非常数指针变量改变常量静态变量时会出现分段错误?

如何在VS 2022中正确安装额外的C头文件

使用ld将目标文件链接到C标准库

如何在c中使用具有不同变量类型的内存分配?

判断系统命令返回值的正确方法

为什么GCC-O1优化破解了这个代码,为了一个GameBoy高级只读存储器而修改了VRAM的循环?

即使我在C++中空闲,也肯定会丢失内存

将复合文字数组用作临时字符串缓冲区是否合理?

C 错误:对 int 数组使用 typedef 时出现不兼容的指针类型问题

为什么 int32_t 和 int16_t 在 printf 输出中具有相同的位数?

如何向 execl 创建的后台程序提供输入?

将十六进制值或十进制值分配给 uint16_t 有什么区别?

使用字符数组声明和字符指针声明进行定义时,c 中的文字如何存储?

当最大成员是原始类型时,联合是否可以大于最大成员?