详解 printf() 函数用法
详解 printf() 函数用法
在C语言中,printf()函数是最常用、最灵活的输出函数之一。它不仅可以输出各种类型的数据,还可以通过格式控制字符串来控制输出的格式。本文将详细介绍printf()函数的用法,包括其定义、输出格式、输出控制符大全以及一些使用技巧和示例代码。
定义
int _cdecl printf(const char *format, ...);
_cdecl
是C和C++程序的缺省调用方式- CDEDL调用约定:
- 参数从右到左依次入栈
- 调用者负责清理堆栈
- 参数的数量类型不会导致编译阶段的错误
- 固定参数
format
(格式控制字符串),包含了两种类型的对象:普通字符和转换说明。 - 在输出时,普通字符将原样不动地复制到标准输出
- 转换说明并不直接输出而是用于控制 printf 中参数的转换和打印。每个转换说明都由一个百分号字符(%)开始,以转换说明结束,从而说明输出数据的类型、宽度、精度等 。
printf 的格式控制字符串 format 中的转换说明组成如下,其中 [] 中的部分是可选的:%[flags][width][.precision][length]specifier,即:%[标志][最小宽度][.精度][类型长度]说明符。(其中,末尾的说明符字符是最重要的组成部分,因为它定义了类型及其相应实参的解释) - 可变参数(用”…”表示)根据不同的 format 字符串,函数可能需要一系列的附加参数,每个参数包含了一个要被插入的值,替换了 format 参数中指定的每个 % 标签。参数的个数应与 % 标签的个数相同。
- 返回值:如果函数执行成功,则返回所打印的字符总数(计数针对所有的打印字符,包括空格和不可见的换行字符),如果函数执行失败,则返回一个负数。
函数调用的参数期望至少有1个!!!
printf() 的正常输出格式
1. 直接输出字符串
#include <stdio.h>
int main(){
printf("hello word!\n");
return 0;
}
其中\n
表示换行的意思,它是一个转义字符。它的意义:换行(LF),将当前位置移到下一行开头。
2. 输出变量值
#include <stdio.h>
int main(){
int i = 10;
printf("%d\n", i);
//%d是输出控制符,d 表示是十进制,后面的 i 是输出参数
return 0;
}
这句话的意思是将变量 i 以十进制输出。那么现在有一个问题:i 本身就是十进制,为什么还要将 i 以十进制输出呢?因为程序中虽然写的是 i=10,但是在内存中并不是将 10 这个十进制数存放进去,而是将 10 的二进制代码存放进去了。计算机只能执行二进制 0、1 代码,而 0、1 代码本身并没有什么实际的含义,它可以表示任何类型的数据。所以输出的时候要强调是以哪种进制形式输出。所以就必须要有“输出控制符”,以告诉操作系统应该怎样解读二进制数据。如果是%x就是以十六进制的形式输出,要是%o就是以八进制的形式输出,大家可以自己试一下。
3. 同时输出多个变量值
#include <stdio.h>
int main(){
int i = 10;
int j = 20;
printf("%d %d", i, j);
return 0;
}
输出控制符 1 对应的是输出参数 1,输出控制符 2 对应的是输出参数 2……编译、链接、执行后我们看一下输出结果:
为什么 10 和 3 之间有一个空格?因为上面 %d 和 %d之间有空格,printf() 中双引号内除了输出控制符外,所有其余的普通字符全部都原样输出。举例如下:
4. 混合输出控制符和普通字符
这个实际上就是上面举的那个例子。这时候会有一个问题:到底什么是“输出控制符”,什么是“非输出控制符”?很简单,凡是以%开头的基本上都是输出控制符; 上面的i =,空格和j =全都原样输出了,这些就是非输出控制符。
输出控制符大全
常用的输出控制符主要有以下几个:
控制符 | 对应数据类型 | 说明 |
---|---|---|
%d \ %i | int | 输出有符号十进制整数(i 是老式写法) |
%ld \ %lld | long \ long long | 输出长整型数据 |
%o | unsigned int | 输出以八进制整数形式(没有前导 0) |
%u | unsigned int | 输出无符号十进制整数 |
%x \ %X | unsigned int | 输出无符号十六进制整数,x 对应的是 abcdef,X 对应的是 ABCDEF(没有前导 0x 或者 0X) |
%c | char | 用来输出一个字符 |
%s | char * | 用来输出字符串。用 %s 输出字符串同前面直接输出字符串是一样的但是此时要先定义字符数组或字符指针存储或指向字符串 |
%f \ %lf | double | 用来输出实数,包括单精度和双精度,以小数形式输出不指定字段宽度,由系统自动指定整数部分全部输出,小数部分输出 6 位,超过 6 位的四舍五入 |
%e(%E) | double | 以浮点数指数输出[e-(E-)记数法] |
%g(%G) | double | 浮点数不显无意义的零"0" |
%p | void * | 以16进制形式输出指针 |
%% | 不转换参数 | 不进行转换,输出字符‘%’(百分号)本身 |
下面是对组成格式说明的各项符号加以说明:
- %:表示格式说明的起始符号,不可缺少。
- -:表示左对齐输出,如省略表示右对齐输出。
- 0:有0表示指定空位填0,如省略表示指定空位不填。
- m.n:m指域宽,即对应的输出项在输出设备上所占的字符数。(如果数据的位数小于 m,则左端补以空格,若大于 m,则按实际位数输出);n指精度。用于说明输出的实型数的小数位数。未指定n时,隐含的精度为n=6位。
- h: 用于将整型的格式字符修正为short型。
- %zu
用来输出
size_t
类型
%x、%X、%#x、%#X 的区别:
因为调试的时候经常要将内存中的二进制代码全部输出,然后用十六进制显示出来。下面写一个程序看看它们四个有什么区别:
# include <stdio.h>
int main(){
int i = 30;
printf("%x\n", i);
printf("%X\n", i);
printf("%#x\n", i);
printf("%#X\n", i);
return 0;
}
以下是代码生成结果(VS-2013):
从输出结果可以看出:如果是小写的x,输出的字母就是小写的;如果是大写的X,输出的字母就是大写的;如果加一个#,就是以标准的十六进制形式输出。但在我们使用过程中,最好是加一个#,否则如果输出的十六进制数正好没有字母的话会误认为是一个十进制数呢!总之,不加#容易造成误解。但是如果输出0x1e或0x1E,那么人家一看就知道是十六进制。而且%#x和%#X中,笔者觉得大写的比较好,因为大写是绝对标准的十六进制写法。
如何输出 %d、\ 和双引号:
printf 中有输出控制符%d,转义字符前面有反斜杠\,还有双引号。那么各位有没有想过这样一个问题:怎样将这三个符号通过 printf 输出到屏幕上呢?
要输出%d只需在前面再加上一个%,要输出\只需在前面再加上一个\,要输出双引号也只需在前面加上一个\即可。程序如下:
# include <stdio.h>
int main(){
printf("%%d\n");
printf("\\\n");
printf("\"\"\n");
return 0;
}
代码生成结果如下:
打印较长字符串:
有时printf 语句会很长,以至于不能在一行被放下,如果我们必须分割一个字符串,有以下三种方式可以选择。需要注意的是,我们可以在字符串中使用 “\n” 换行符来表示换行字符,但是在字符串中不能通过回车键来产生实际的换行字符。
示例代码:
#include <stdio.h>
int main() {
//方式一:使用多个printf语句
printf("Here's one way to print a ");
printf("long string.\n");
//方式二:使用反斜杠 "\" 加回车的组合来进行分割,注意下一行要从最左侧开始,否则缩进会成为该字符串的一部分
printf("Here's another way to print a \
long string.\n");
//方式三:采用字符串连接的方法,中间不能有逗号,可以是空格或者回车
printf("Here's the newest way to print a "
"long string.\n");
return 0;
}
//程序运行结果:
Here's one way to print a long string.
Here's another way to print a long string.
Here's the newest way to print a long string.
总结
printf 是C语言中非常重要的一个函数。经过上面的学习我们发现,其实它并不难。只要多编程多练习,很快就能掌握。输出控制符中,%d、%f、%s、%c 是最常用的,它们分别是输出整数、实数、字符串和字符的控制符。%.mf 虽然用得不多,但一定要重视。