深入了解printf的用法和各类变形之区别

本文详细介绍了printf家族的函数,包括printf、fprintf、sprintf和snprintf等,阐述了它们的功能和返回值。此外,还提到了在Keil集成开发环境中,为了优化嵌入式设备的代码空间,提供了下划线开头的变体,这些变体不支持浮点格式,但具有更高的效率。

int printf(const char *format, ...);  向默认的标准输出设备按照规定格式输出信息,返回值为打印的字符个数,不包括结束符。例如正常执行printf("1234");printf("%d",1234)返回值都为4,输出失败(没有输出全部字符)则返回负数。

int fprintf(FILE *stream, const char *format, ...);向指定的输出设备按照规定格式输出信息,返回值同上
int sprintf(char *str, const char *format, ...);向指定的内存缓冲区按照规定的格式输出信息,返回值同上
int snprintf(char *str, size_t size, const char *format, ...);向指定长度的缓冲区按照规定格式输出字符串,如果进行格式输出字符串超过缓冲区长度,则只输出缓冲区长度减1个字符,且末尾加字符串结束符\0,如果缓冲区长度大于字符串长度,则字符串全部输出到缓冲区,末尾加\0.返回值同上。


int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);

以上4个带v的printf实际上是为用户重新实现可变参数函数设计的,例如假设我们需要实现一个log函数,其功能是打印日志,打印信息被输出到串口,输入参数可变。怎么实现?

int log(int a,int b,int c,const char *format,...)
{
	 va_list ap;
	char str[100];
	//处理相关信息
        
<think> 我们正在讨论fprintfprintf区别。根据引用[1]引用[2],这两个函数都是C语言中用于格式化输出的函数,主要区别在于它们输出的目标不同。 引用[1]指出:fprintf适用于所有文件输出流,而printf默认输出到标准输出(stdout)。实际上,printf可以看作fprintf的一个特例,即: printf("hello world\n") 等价于 fprintf(stdout, "hello world\n") 引用[2]也明确说明:printf将输出显示在屏幕上,而fprintf可以将输出写入到指定的文件中。 因此,它们的主要区别如下: 1. 输出目标: - printf:总是输出到标准输出(stdout),通常是屏幕。 - fprintf:输出到指定的文件流(FILE*),可以是任何文件,包括标准输出(stdout)、标准错误(stderr)或者磁盘文件。 2. 函数原型: - printf: int printf(const char *format, ...); - fprintf: int fprintf(FILE *stream, const char *format, ...); 3. 使用场景: - 当需要将内容输出到屏幕时,使用printf更简洁。 - 当需要将内容输出到文件(如日志文件)或者其他流(如stderr)时,必须使用fprintf。 另外,引用[3]虽然讲的是Go语言,但原理类似,fmt.Fprintf的第一个参数指定了输出的目标(实现了io.Writer接口的对象),这与C语言的fprintf类似。 举例说明: - 使用printf输出到屏幕: printf("This is a message on screen.\n"); - 使用fprintf输出到标准输出(等同于printf): fprintf(stdout, "This is also on screen.\n"); - 使用fprintf输出到标准错误(stderr): fprintf(stderr, "This is an error message.\n"); - 使用fprintf输出到文件: FILE *fp = fopen("log.txt", "w"); if (fp) { fprintf(fp, "Write to a file.\n"); fclose(fp); } 注意:在程序中,如果我们需要将错误信息输出到标准错误流(stderr)而不是标准输出(stdout),通常使用fprintf(stderr, ...),这样可以确保错误信息即使标准输出被重定向到文件时也能在屏幕上显示。 总结: printf是fprintf的一个特例,专用于标准输出。fprintf则更通用,可以指定输出流。 相关问题: 1. 在C语言中,如何将输出同时重定向到屏幕文件? 2. 除了printffprintf,还有哪些常用的格式化输出函数? 3. 如何用fprintf实现类似printf的功能? 4. 标准错误(stderr)标准输出(stdout)有什么区别? 根据用户之前的提问,我们还要注意之前讨论过为什么回退到stderr而不是stdout(因为stderr是无缓冲的,能确保错误信息及时输出)。因此,在需要立即输出错误信息时,我们通常使用fprintf(stderr, ...)或者使用printf(但printf输出到stdout,可能被缓冲,所以错误信息最好用stderr)。 </think> ### fprintfprintf区别详解 #### 1. **核心区别:输出目标不同** - **`printf`函数**: ```c int printf(const char *format, ...); // 标准形式 ``` - **始终输出到标准输出流 `stdout`** - 默认显示在终端屏幕 - 示例:`printf("Hello")` → 屏幕显示 "Hello"[^1][^2] - **`fprintf`函数**: ```c int fprintf(FILE *stream, const char *format, ...); // 标准形式 ``` - **可指定任意输出流**(通过`stream`参数) - 支持多种输出目标: ```c fprintf(stdout, "Hello"); // 等效于printf fprintf(stderr, "Error!"); // 输出到标准错误 fprintf(file_ptr, "Data"); // 写入文件 ``` #### 2. **底层关系** 两者本质共享相同的格式化引擎[^4],存在等价关系: $$ \text{printf}(...) \equiv \text{fprintf}(\text{stdout}, ...) $$ 这意味着: - `printf` 是 `fprintf` 的特化版本 - `fprintf` 是更通用的输出函数[^1] #### 3. **使用场景对比** | **场景** | **推荐函数** | **原因** | |------------------------|--------------|------------------------------| | 向屏幕输出普通信息 | `printf` | 代码简洁,无需指定流 | | 向屏幕输出错误/警告 | `fprintf(stderr)` | 避免缓冲延迟,即时显示[^4] | | 写入日志文件 | `fprintf(file)` | 精确控制输出位置 | | 多目标输出(如屏幕+文件)| `fprintf` | 可通过不同流参数复用相同格式 | #### 4. **缓冲特性差异** - `printf(stdout)` 使用**行缓冲**: - 遇换行符 `\n` 或缓冲区满才刷新 - 示例:`printf("A"); printf("B");` 可能延迟显示 - `fprintf(stderr)` 使用**无缓冲**: - 立即刷新,适合关键信息输出 - 示例:`fprintf(stderr, "CRITICAL!");` 即时可见 #### 5. **代码示例对比** ```c // 场景1:普通屏幕输出 printf("当前温度:%.1f°C\n", 25.5); // 输出到stdout // 场景2:错误处理 FILE *log = fopen("app.log", "a"); if(!log) { // 文件打开失败时回退到stderr fprintf(stderr, "[ERR] 日志文件不可用\n"); } else { // 正常写入日志文件 fprintf(log, "[INFO] 系统启动\n"); } ``` #### 6. **设计哲学** - **`printf`**: 面向人机交互场景 遵循UNIX“简单性原则”,提供最简输出接口 - **`fprintf`**: 面向系统编程场景 符合UNIX“一切皆文件”理念,通过流抽象统一I/O操作 --- ### 总结对比表 | **特性** | `printf` | `fprintf` | |----------------|-------------------|-------------------------| | 输出目标 | 固定为`stdout` | 可指定任意文件流 | | 缓冲机制 | 行缓冲 | 取决于目标流(如stderr无缓冲) | | 使用复杂度 | ★☆☆ (简单) | ★★☆ (中等) | | 灵活性 | 低 | 高 | | 典型应用场景 | 命令行交互输出 | 日志记录、错误报告、文件操作 | > 💡 **经验法则**: > 当仅需屏幕输出时用 `printf`; > 需要文件/错误流输出时必用 `fprintf` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值