高二C语言基础
第一章 1.1 C语言概述
第一章 1.2 C语言的特点
01.VS开发环境的搭建
02.第一个C语言程序
03.C语言基础语法知识
04.整型数据类型
05.浮点数据类型
06.变量与常量
07.字符常量及字符变量
08.printf函数详细解析(上)
汝城县职业中等专业学校知识库-信息中心朱老师编辑
-
+
首页
08.printf函数详细解析(上)
08.printf函数详细解析(上)
## 1. printf函数使用公式 在前几篇文章中,我们已经使用过很多次 printf 函数了。 这一节,我们先复习一下 printf 的使用公式,然后再来详细讨论一下它。 printf 函数的使用公式: ### printf("XXX占位1 XXX 占位2 XXX占位3", 替换1, 替换2, 替换3); 根据公式,我们写出以下示例代码。 ``` #include <stdio.h> int main() { int a = 1; float b = 2.345; char c = 'a'; printf("整型a为%d 浮点b为%f 字符c为%c 字符c对应的ASCII码为%d", a, b, c, c); return 0; } ```  让我们从以下5点详细分析一下 printf 的用法: **1. printf 是一个变参函数。(参数的数量和类型不确定) 2. printf 的第一个参数是字符串。 3. printf 的第一个参数是需要输出的字符以及需要被替换的占位符。 你好编程 4. printf 的第二及后续参数将依次替换占位符。 5. 占位符的类型和数量需要与后续的参数类型和数量对应。** ### 1.1 printf是一个变参函数 关于 printf 是一个变参函数的事实,我们在前面对 printf 的使用中,已经充分验证过了。 它的参数个数是不确定的,同时参数类型也是不确定的。 ``` printf("%d", 1); // 两个参数 printf("%d %f", 1, 2.3); // 三个参数 printf("%d %f %c", 1, 2.3, 'H'); // 四个参数 ``` ### 1.2 第一个参数必须字符串  ### 1.3 第一个参数包含需要输出的字符以及需要被替换的占位符  这个字符串包含了需要输出的字符,以及需要被替换的占位符。 ### 1.4 第二及后续参数将依次替换占位符  ### 1.5 占位符的类型和数量需要与后续的参数类型和数量对应  ## 2. 整型类型的占位符 在前面的 printf 函数的使用当中,我们一直将 %d 作为整型 int 类型的占位符。对于其他的整型类型,它们的占位符分别都是什么呢? printf 是一个可变参数函数,在C语言中将参数传入函数的可变参数中,变量会发生自动类型提升。 ### 2.1 有符号整型的类型提升 对于有符号位的整型 char , short ,传入 printf 的可变参数时,会被提升为 int 。而比 int 更高级的整型则不发生变化。  >i **信息提示** > > 所以,在处理 char , short , int 时,均可使用 %d 来占位。 而在Visual Studio中 int 与 long 的范围一致,按理来说也可以使用 %d 来占位。 但是为了程序的可移植性,在切换到别的平台下时, int 和 long 有可能不一致。 所以,请使用 %ld 来为 long 占位。更高级的 long long 则需要使用 %lld 来占位。 >s **结论** char,short,int使用 %d 。 long使用 %ld 。 long long使用 %lld 。 ### 2.2 无符号整型的类型提升 对于无符号位的整型 unsigned char , unsigned short ,传入 printf 的可变参数时,会被提升 为 unsigned int 。而比 unsigned int 更高级的整型则不发生变化。  对于无符号整型,需要将 d 替换成 u 表明最高位不被看作符号位,而是数据位。 >s **结论** unsigned char,unsigned short,unsigned int使用 %u 。 unsigned long使用 %lu 。 unsigned long long使用 %llu 。 ### 2.3 浮点类型的类型提升 float 会被提升为 double , double 不发生变化。 >s **结论** float,double均使用 %f 。 ### 3. 转换规范 为了易于理解,前面称 以%开始的一串字符 为 占位符 。这是一个为了让大家理解的说法,其实这个说法并不准确。更准确地说,它们应该被称为转换规范。 ### 3.1 转换规范总览 转换规范以%百分号开始,依次具有下面这些元素: 1. 零个或多个**标志**字符(-,+,0,#)。 2. 一个可选的十进制整数常量表示的**最小字段宽度**。 3. 一个可选的用点号表示的**精度**范围,它的后面可以跟一个十进制整数。 4. 一个可选的**长度指示符**,可以用下列字母组合之一来表示:h、hh、l、LL,z。 5. 由单个字符表示的**转换操作**,取自下面这个集合:c、d、e、E、f、i、o、s、u、x、X。 6.  ### 3.2 转换操作 我们先讨论转换规范的最后一个部分—— 转换操作  **转换操作**由单个字符表示,取自下面这个集合: c、d、e、E、f、i、o、s、u、x、X 。 printf可以根据 转换操作 使用不同的 转换方式 ,取 n字节的二进制数据 并转换成字符。  ### 3.3 转换操作d ``` #include <stdio.h> int main() { char c1 = 127; short s1 = 32767; int n1 = 2147483647; char c2 = -128; short s2 = -32768; int n2 = -2147483648; printf("%d\n", c1); printf("%d\n", s1); printf("%d\n", n1); printf("%d\n", c2); printf("%d\n", s2); printf("%d\n", n2); return 0; } ```  变量c1,s1,c2,s2均为比int低级的整型类型。它们在进入printf时会转==换为int==。因此使用转换操作d,取==sizeof(int)字节==二进制数据,并将它们按照有==符号整型==转换为字符并打印在控制台上。 ### 3.4 转换操作u ``` #include <stdio.h> int main() { unsigned char c1 = 0; unsigned short s1 = 0; unsigned int n1 = 0; unsigned char c2 = 255; unsigned short s2 = 65535; unsigned int n2 = 4294967295; printf("%u\n", c1); printf("%u\n", s1); printf("%u\n", n1); printf("%u\n", c2); printf("%u\n", s2); printf("%u\n", n2); return 0; } ```  变量c1,s1,c2,s2均为比unsigned int低级的整型类型。它们在进入printf时会转换为unsigned int。因此使用转换操作u,==取sizeof(unsigned int)字节二进制数据==,并将它们按照无符号整型转换为字符并打印在控制台上。 ### 3.5 误用转换操作d与u 由于有符号整型int与无符号整型int的取值范围不一致,数据类型与转换操作错误搭配很有可能造成错误的转换结果。  ***int的取值范围为-2147483648~2147483647。*** ***unsigned int的取值范围为0~4294967295。*** ### 3.5.1 取值范围在共有范围中 ``` #include <stdio.h> int main() { int n = 2147483647; unsigned int u = 2147483647; // n printf("n = %d\n", n); printf("n = %u\n", n); // u printf("u = %d\n", u); printf("u = %u\n", u); return 0; } ```  取值范围在共有范围中,无论使用 u 还是 d 进行转换,均能得到正确的结果。 ### 3.5.2 取值范围不在共有范围中 ``` #include <stdio.h> int main() { int n = -1; unsigned int u = 4294967295; // 打印n printf("n=%d\n", n); printf("n=%u\n", n); // 打印u printf("u=%d\n", u); printf("u=%u\n", u); return 0; } ```  -1为有符号整型int的取值范围,使用 d 可以正常打印,而 u 却出错。 4294967295为无符号整型unsigned int的取值范围,使用 u 可以正常打印,而 d 却出错。 **为了保证转换正确,请严格使用与类型对应的转换操作。** ### 3.5.3 注意数据类型的取值范围 ``` #include <stdio.h> int main() { char c = 200; unsigned short s = -32768; int n = 4294967296; printf("c=%d\n", c); printf("s=%d\n", s); printf("n=%d\n", n); printf("c=%u\n", c); printf("s=%u\n", s); printf("n=%u\n", n); return 0; } ```  上面无论是使用 u 或 d 结果都出错了,这是为什么呢? char的取值范围为-128到127,而初始化时给了200。 unsigned short不可以初始化为一个负数。 int最大值为2147483647。 **它们初始化的值均超过了它们可以容纳的数值范围,本身的变量数值已经出错**,无论怎样都无法得到正确的结果。 ### 3.6 转换操作c ``` #include <stdio.h> int main() { char c = 65; short s = 66; int n = 67; printf("c=%d\n", c); printf("s=%d\n", s); printf("n=%d\n", n); printf("c=%c\n", c); printf("s=%c\n", s); printf("n=%c\n", n); return 0; } ```  变量c,s,n 为比int低级或等于的整型类型。它们在进入printf时会**转换为int**。因此使用转换操作c,**取sizeof(int) **字节二进制数据,将数值转换为**数值对应的ASCII字符**并打印在控制台上。 ### 3.7 转换操作f,e,E ``` #include <stdio.h> int main() { float f = 1.234; double df = 1.234567; printf("%f\n", f); printf("%f\n", df); return 0; } ```  变量f, df 为比double低级或等于的整型类型。它们在进入printf时会转换为double。因此使用转换操作f,取 sizeof(double) 字节二进制数据,并将它们按照双精度浮点型转换为字符并打印在控制台上。 ``` #include <stdio.h> int main() { float f = 1.234; double df = 1.234567; printf("%e\n", f); printf("%e\n", df); printf("%E\n", f); printf("%E\n", df); return 0; } ```  **转换操作e,E与f类似,但是使用e计数法。e与E的区别为,一个使用小写e,一个使用大写E。** ### 3.8 转换操作o,x,X ``` #include <stdio.h> int main() { unsigned int n = 123456; printf("%u\n", n); // 十进制 printf("%o\n", n); // 八进制 printf("%x\n", n); // 十六进制,小写字母 printf("%X\n", n); // 十六进制,大写字母 return 0; } ```  o,x,X 转换操作,将==获取sizeof(unsigned int)字节二进制数据==。 **o将数据按照无符号整型**转换为**八进制**字符并打印在控制台上。 x,X将数据按照**无符号整型**转换为**十六进制**字符并打印在控制台上。 x与X的不同在于,一个使用小写字母,一个使用大写字母。 ### 3.9 转换操作s ``` #include <stdio.h> int main() { printf("%s", "Hello World\n"); return 0; } ```  **s 转换操作,将获取 sizeof(char *) 字节二进制数据,并将这个数据看作字符串首地址,从首地址开 始,输出这串字符串。**
admin
2025年9月22日 18:41
64
0 条评论
转发
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
Word文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码
有效期
AI