c - 使用 %ld 转换说明符在 C 中打印 double 类型

标签 c linux gcc

这是部分源代码(示例代码来自《C primer plus》一书):

float n1 = 3.0;
double n2 = 3.0;
long n3 = 2000000000;
long n4 = 1234567890;
printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);

预期的输出是:

0 1074266112 0 1074266112

书中明确说明原因:

The mechanics of argument passing depend on the implementation. This is how argument passing works on one system. The function call looks as follows:
printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);
This call tells the computer to hand over the values of the variables n1 , n2 , n3 , and n4 to the computer. Here’s one common way that’s accomplished. The program places the values in an area of memory called the stack . When the computer puts these values on the stack, it is guided by the types of the variables, not by the conversion specifiers. Consequently, for n1 , it places 8 bytes on the stack ( float is converted to double ). Similarly, it places 8 more bytes for n2 , followed by 4 bytes each for n3 and n4 . Then control shifts to the printf() function. This function reads the values off the stack but, when it does so, it reads them according to the conversion specifiers. The %ld specifier indicates that printf() should read 4 bytes, so printf() reads the first 4 bytes in the stack as its first value. This is just the first half of n1 , and it is interpreted as a long integer. The next %ld specifier reads 4 more bytes; this is just the second half of n1 and is interpreted as a second long integer (see Figure 4.9 ). Similarly, the third and fourth instances of %ld cause the first and second halves of n2 to be read and to be interpreted as two more long integers, so although we have the correct specifiers for n3 and n4 , printf() is reading the wrong bytes.

我可以得到书上说的,并且我自己的PC用于每种数据类型的内存与上面相同。
但是当我自己编译并运行代码时,我得到以下输出:
2000000000 1234567890 2147483626 0
我的开发环境是:Ubuntu16.04LTS,gcc 5.4.0,C11标准。
我不知道是什么导致我自己的输出和预期的不同。

最佳答案

Here’s one common way that’s accomplished. The program places the values in an area of memory called the stack . When the computer puts these values on the stack, it is guided by the types of the variables, not by the conversion specifiers

这在大多数 32 位系统上是正确的,但在 64 位系统上,调用约定不同,并且尽可能在寄存器中传递参数。

参见 this (System V AMD64 ABI 与此处相关)。

确保的一种方法是查看程序的汇编输出。使用 gcc,您可以使用 -S 输出程序集而不是二进制文件。

(请注意,我在这里只谈论 linux。情况可能会有所不同,具体取决于您的操作系统,并且由于这是未定义的行为,您的编译器甚至您的编译器版本或标志)

关于c - 使用 %ld 转换说明符在 C 中打印 double 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48697853/

相关文章:

c - Netbeans 8.1 C 调试器错误?

c - 内存栅栏如何工作?

c - 如何用 Hoare Triple 验证该功能?

c - 如何在用 C 编写的 GLUT 程序上设置关闭操作? (如左上角红色按钮工作)

linux - Cuda 编译器不适用于 GCC 4.5 +

c++ - 模板编译: gcc vs VS2010

c - Cygwin 中的段错误和默认变量初始化

linux:目录中的最新文件,不包括目录和 .文件

python - 如何告诉 f2py 模块在当前目录中查找共享对象依赖项

linux - 用 bash 设置参数