欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C中printf()转换不匹配问题

程序员文章站 2022-06-03 13:12:02
...

来源C Primer Plus page 208
1./* intconv.c – 一些不匹配的整型转换 */

/* intconv.c -- 一些不匹配的整型转换 */
#include <stdio.h>
#define PAGES 336
#define WORDS 65618
int main(void)
{
	short num = PAGES;
	short mnum = -PAGES;
	printf("%hd %hu\n", num, num);
	printf("%hd %hu\n", mnum, mnum);/*结果65200将负数在内存中的补码形式以无符号数输出*/
	printf("%d %c\n", num, num);
	printf("%d %hd %c\n", WORDS,WORDS,WORDS);
	getchar();/*方便看结果*/
	return 0;
}
/*整形转换,根据转换说明在内存中截取所需部分或者转化成所需形式*/
/*vs2017结果:
336 336
-336 65200
336 P
65618 82 R*/

2./* floatcnv.c – 不匹配的浮点型转换 */

/* floatcnv.c -- 不匹配的浮点型转换 */
#include <stdio.h>
int main(void)
{
	float n1 = 3.0;
	double n2 = 3.0;
	long n3 = 2000000000;
	long n4 = 1234567890;
	printf("%.1e %.1e %.1e %.1e\n", n1, n2, n3, n4);/*float类型的值作为printf()参数时会被
转换成double类型*/
	printf("%ld %ld\n", n3, n4);
	printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);
	printf("%ld %ld\n", n1, n2);
	printf("%ld %ld\n", n1, n3);
	printf("%ld %ld\n", n1, n4);
	printf("%ld %ld\n", n3, n1);
	printf("%ld %ld %ld %ld %ld %ld\n", n1, n2, n3, n4);/*计算机把n1,n2,n3,n4这些变量或常量或表达式(根据数据类型确定存储字节)的值放入被称为栈(stack)的内存区域,然后根据转换说明选取所需字节的数据转换出来*//*最后一个printf的输出结果可以证明*/
	getchar();/*方便看结果*/
	return 0;
}
/*vs2017运行结果
3.0e+00 3.0e+00 3.1e+46 6.2e-304
2000000000 1234567890
0 1074266112 0 1074266112
0 1074266112
0 1074266112
0 1074266112
2000000000 0
0 1074266112 0 1074266112 2000000000 1234567890*/

详细说明(来源C Primer Plus page211):
第1行输出显示,%e转换说明没有把整数转换成浮点数。考虑一下,如果使用%e转换说明打印n3(long类型)会发生什么情况。首先,%e转换说明让printf()函数认为待打印的值是double类型(本系统中double为8字节)。当printf()查看n3(本系统中是4字节的值)时,除了查看n3的4字节外,还会查看查看n3相邻的4字节,共8字节单元。接着,它将8字节单元中的位组合解释成浮点数(如,把一部分位组合解释成指数)。因此,即使n3的位数正确,根据%e转换说明和%ld转换说明解释出来的值也不同。最终得到的结果是无意义的值。
第1行也说明了前面提到的内容:float类型的值作为printf()参数时会被转换成double类型。在本系统中,float是4字节,但是为了printf()能正确地显示该值,n1被扩成8字节。
第2行输出显示,只要使用正确的转换说明,printf()就可以打印n3和n4。
第3行输出显示,如果printf()语句有其他不匹配的地方,即使用对了转换说明也会生成虚假的结果。用%ld转换说明打印浮点数会失败,但是在这里,用%ld打印long类型的数竟然也失败了!问题出在C如何把信息传递给函数。具体情况因编译器实现而异。“参数传递”框中针对一个有代表性的系统进行了讨论。
参数传递
参数传递机制因实现而异。下面以我们的系统为例,分析参数传递的原理。函数调用如下:

   printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);

该调用告诉计算机把变量n1、n2、、n3和n4的值传递给程序。这是一种常见的参数传递方式。程序把传入的值放入被称为栈(stack)的内存区域。计算机根据变量类型(不是根据转换说明)把这些值放入栈中。因此,n1被储存在栈中,占8字节(float类型被转换成double类型)。同样,n2也在栈中占8字节,而n3和n4在栈中分别占4字节。然后,控制转到printf()函数。该函数根据转换说明(不是根据变量类型)从栈中读取值。%ld转换说明表明printf()应该读取4字节,所以printf()读取栈中的前4字节作为第1个值。这是n1的前半部分,将被解释成一个long类型的整数。根据下一个%ld转换说明,printf()再读取4字节,这是n1的后半部分,将被解释成第2个long类型的整数(见图4.9)。类似地,根据第3个和第4个%ld,printf()读取n2的前半部分和后半部分,并解释成两个long类型的整数。因此,对于n3和n4,虽然用对了转换说明,但printf()还是读错了字节。

float n1; /* 作为double类型传递 */
double n2;
long n3, n4;
...
printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);

C中printf()转换不匹配问题

相关标签: printf