为什么ints有时要求双倍';s的打印格式是C?
我敢肯定,其他一些人也对这一点感到困惑,因为我也是 在基于转换函数的工作中,我想先测试一些东西,然后再开始制作一个将整数转换为浮点或双精度的函数 所以我在C99中写的是:为什么ints有时要求双倍';s的打印格式是C?,c,floating-point,integer,C,Floating Point,Integer,我敢肯定,其他一些人也对这一点感到困惑,因为我也是 在基于转换函数的工作中,我想先测试一些东西,然后再开始制作一个将整数转换为浮点或双精度的函数 所以我在C99中写的是: #include <stdio.h> int main() { int number = 200; printf("%f\n", number); } 现在我很困惑,我认为%f只适用于float和double,但是%d处理double和int。因此,我尝试用建议修复程序,结果
#include <stdio.h>
int main() {
int number = 200;
printf("%f\n", number);
}
现在我很困惑,我认为%f
只适用于float
和double
,但是%d
处理double
和int
。因此,我尝试用建议修复程序,结果只是一个数字,而不是一个浮点值,这让我很困惑:
~/BPML/C/Part3/Conversion/ $ make make_float
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow make_float.c -lcrypt -lcs50 -lm -o make_float
~/BPML/C/Part3/Conversion/ $ ./make_float
200
~/BPML/C/Part3/Conversion/ $
问:为什么
printf
让int
用%d
打印出来,如果它代表double
或decimal?您得到的错误是预期的:格式%f
需要双参数。您传递了一个int
,这样编译器就可以正确地捕捉到错误。f
代表“浮点”,即在打印输出中可能需要小数点的数字double
是一种浮点类型
同样,格式%d”
需要int
参数。您不能传递double
。格式字符串中的d
表示“十进制”,而x
表示“十六进制”,o
表示“八进制”,甚至u
表示无符号。所有这些转换都需要int
或无符号int
参数。%d”
格式输出十进制格式的整数,因此需要一个int
参数
不能用浮点值代替整数参数,反之亦然。如果int
是鱼,double
是植物。它们不能互换使用
当您将小于int
或double
的类型作为printf()
参数传递时,C语言将隐式转换该参数char
和short
将提升为int
,而float
将提升为double
。这就是为什么可以对%d”
格式使用char
参数,或者对%f”
格式使用float
参数的原因。升级后,每个参数都会获得所需的类型。预期会出现错误:格式%f”
需要一个双参数。您传递了一个int
,这样编译器就可以正确地捕捉到错误。f
代表“浮点”,即在打印输出中可能需要小数点的数字double
是一种浮点类型
同样,格式%d”
需要int
参数。您不能传递double
。格式字符串中的d
表示“十进制”,而x
表示“十六进制”,o
表示“八进制”,甚至u
表示无符号。所有这些转换都需要int
或无符号int
参数。%d”
格式输出十进制格式的整数,因此需要一个int
参数
不能用浮点值代替整数参数,反之亦然。如果int
是鱼,double
是植物。它们不能互换使用
当您将小于int
或double
的类型作为printf()
参数传递时,C语言将隐式转换该参数char
和short
将提升为int
,而float
将提升为double
。这就是为什么可以对%d”
格式使用char
参数,或者对%f”
格式使用float
参数的原因。升级后,每个参数都会获得所需的类型。C标准中的说明:
“%d”
需要int
。从C11草案7.21.6.1中,fprintf
函数-8(与printf()
相同):
d、 i将int
参数转换为有符号十进制
提供错误的类型会导致UB。从C11草案7.21.6.1中,fprintf
函数-9
9如果转换规范无效,则行为未定义。
275)如果任何参数的类型不正确
转换规范,行为未定义
printf()
使用与fprintf()
相同的格式和规则。从C11草案7.21.6.3中,printf
功能-2:
2 printf函数等价于带参数的fprintf
stdout在printf的参数之前插入
请注意,有一个提升,float
被提升为double
,因此当printf()
需要double
时,使用float
可以,因此%f
适用于double
和float
。根据C11草案,6.5.2.2函数调用-6-7:
6如果表示被调用函数的表达式的类型
不包括原型,整数升级在
每个参数和具有float类型的参数都升级为
双重的这些被称为默认参数
7如果表示被调用函数的表达式的类型
如果包含原型,参数会隐式转换,如下所示
如果按赋值,则对应参数的类型,取
每个参数的类型是其非限定版本
声明的类型。函数原型中的省略号表示法
声明符导致参数类型转换在最后一个
声明的参数。默认值
~/BPML/C/Part3/Conversion/ $ make make_float
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow make_float.c -lcrypt -lcs50 -lm -o make_float
~/BPML/C/Part3/Conversion/ $ ./make_float
200
~/BPML/C/Part3/Conversion/ $
Address Data
+-------+-------+
| 0x42 | arg0 | <-- Stack pointer points here.
+-------+-------+
| 0x41 | arg1 |
+-------+-------+
| 0x40 | arg2 |
+-------+-------+
| 0x3F | arg3 |
+-------+-------+
Addres Data
+-------+-------------+
| 0x44 | ap | <-- local variables of foo()
+-------+-------------+
| 0x43 | returnAdd | <-- caller address
+-------+-------------+
| 0x42 | arg0 |
+-------+-------------+
| 0x41 | arg1 | <-- ap points here
+-------+-------------+
| 0x40 | arg2 |
+-------+-------------+
| 0x3F | arg3 |
+-------+-------------+
Addres Data
+-------+-------------+
| 0x44 | ap | <-- local variables of foo()
+-------+-------------+
| 0x43 | returnAdd | <-- caller address
+-------+-------------+
| 0x42 | arg0 |
+-------+-------------+
| 0x41 | arg1 |
+-------+-------------+
| 0x40 | arg2 | <-- ap points here
+-------+-------------+
| 0x3F | arg3 |
+-------+-------------+