欢迎光临
我们一直在努力

C 语言:彻底搞懂 printf 与 scanf 的作用、数据流向以及常见误区

摘要:本文围绕 C 语言中最基础也最易混淆的一对标准库函数 printf 与 scanf 展开,先分别讲清二者的作用、基础语法、常用占位符与数据流向,再重点剖析 scanf 的返回值、%c 与 %lf 等占位符陷阱以及 VS 环境下的 C6031 警告处理;随后澄清「两个函数必须成对出现、数据直接传递」的常见误区,指出变量内存才是真正的数据中转站;最后汇总初学者高频踩坑,并用一张对比表从作用、数据流向、是否阻塞、参数是否加 &、返回值含义、%f 与 %lf 差异、是否跳过空白字符等维度横向对比二者,帮助读者一次性建立清晰、可落地的认知。

学 C 语言,最先接触、也最容易混淆的一对函数,就是 printf 和 scanf。很多人会简单记成“一个输出、一个输入”,但问到二者之间到底是什么关系,常常说不清楚:它们是不是必须成对出现?scanf 的数据是直接传给 printf 的吗?

这篇文章就把 scanf、printf 的各自作用、数据流向以及常见误区一次性讲明白。

前置:两个函数都来自标准输入输出库,使用必须引入头文件

#include <stdio.h>

一、printf:格式化输出,程序向屏幕输出内容

printf 全称 print format,名字中的 f 代表 format(格式化)。
作用:把程序内存中的常量、变量,按照我们定制的格式输出到标准输出设备(屏幕 stdout)。

数据流向:程序内存(变量/常量) → printf → 屏幕(stdout标准输出)

printf 的数据流向可以用下图表示:

#mermaid-svg-8b8jrk8ZENfUzMUV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8b8jrk8ZENfUzMUV .error-icon{fill:#552222;}#mermaid-svg-8b8jrk8ZENfUzMUV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8b8jrk8ZENfUzMUV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8b8jrk8ZENfUzMUV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8b8jrk8ZENfUzMUV .marker.cross{stroke:#333333;}#mermaid-svg-8b8jrk8ZENfUzMUV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8b8jrk8ZENfUzMUV p{margin:0;}#mermaid-svg-8b8jrk8ZENfUzMUV .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster-label text{fill:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster-label span{color:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster-label span p{background-color:transparent;}#mermaid-svg-8b8jrk8ZENfUzMUV .label text,#mermaid-svg-8b8jrk8ZENfUzMUV span{fill:#333;color:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV .node rect,#mermaid-svg-8b8jrk8ZENfUzMUV .node circle,#mermaid-svg-8b8jrk8ZENfUzMUV .node ellipse,#mermaid-svg-8b8jrk8ZENfUzMUV .node polygon,#mermaid-svg-8b8jrk8ZENfUzMUV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8b8jrk8ZENfUzMUV .rough-node .label text,#mermaid-svg-8b8jrk8ZENfUzMUV .node .label text,#mermaid-svg-8b8jrk8ZENfUzMUV .image-shape .label,#mermaid-svg-8b8jrk8ZENfUzMUV .icon-shape .label{text-anchor:middle;}#mermaid-svg-8b8jrk8ZENfUzMUV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8b8jrk8ZENfUzMUV .rough-node .label,#mermaid-svg-8b8jrk8ZENfUzMUV .node .label,#mermaid-svg-8b8jrk8ZENfUzMUV .image-shape .label,#mermaid-svg-8b8jrk8ZENfUzMUV .icon-shape .label{text-align:center;}#mermaid-svg-8b8jrk8ZENfUzMUV .node.clickable{cursor:pointer;}#mermaid-svg-8b8jrk8ZENfUzMUV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8b8jrk8ZENfUzMUV .arrowheadPath{fill:#333333;}#mermaid-svg-8b8jrk8ZENfUzMUV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8b8jrk8ZENfUzMUV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8b8jrk8ZENfUzMUV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8b8jrk8ZENfUzMUV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8b8jrk8ZENfUzMUV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8b8jrk8ZENfUzMUV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster text{fill:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV .cluster span{color:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8b8jrk8ZENfUzMUV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8b8jrk8ZENfUzMUV rect.text{fill:none;stroke-width:0;}#mermaid-svg-8b8jrk8ZENfUzMUV .icon-shape,#mermaid-svg-8b8jrk8ZENfUzMUV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8b8jrk8ZENfUzMUV .icon-shape p,#mermaid-svg-8b8jrk8ZENfUzMUV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8b8jrk8ZENfUzMUV .icon-shape .label rect,#mermaid-svg-8b8jrk8ZENfUzMUV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8b8jrk8ZENfUzMUV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8b8jrk8ZENfUzMUV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8b8jrk8ZENfUzMUV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

程序内存变量 / 常量

printf 格式化

屏幕 stdout

1.1 基础语法

printf("格式字符串", 参数1, 参数2, …);

  • 格式字符串内可以写普通文本,也可以写 % 开头的占位符;
  • 占位符和后面参数一一对应:如果格式串内有 n 个占位符,则一共需要 n + 1 个参数;参数数量不足,会读取内存随机垃圾值;
  • printf 不会自动换行,想要换行需要手动写转义字符 \\n。

简单示例:

#include <stdio.h>
int main(void)
{
int num = 66;
printf("数字的值 = %d\\n", num);
printf("Hello\\nWorld\\n"); // \\n 实现换行
return 0;
}

1.2 常用占位符对照表(和 C 内置数据类型匹配)

占位符含义
%d / %i 打印 int 十进制有符号整数
%hd 打印 short 短整型
%ld 打印 long 长整型
%lld 打印 long long 长长整型
%u 打印 unsigned int 无符号整数
%f 打印 float / double 浮点数,默认小数点后 6 位
%c 打印单个字符
%s 打印字符串
%zd 打印 size_t 类型,配合 sizeof 使用
%p 打印指针/内存地址
%% 输出一个百分号%

1.3 拓展:格式化输出小技巧

  • 限定输出宽度:%5d 代表最小占 5 字符宽度,不足补空格,默认右对齐;%-5d 加负号改为左对齐。
  • printf("%5d\\n", 123); // 输出: 123
    printf("%-5d\\n", 123); // 输出:123

  • 控制小数精度:%.2f,保留小数点后 2 位。
  • printf("Number is %.2f\\n", 0.5); // Number is 0.50

    💡执行特性:printf 执行时不会阻塞程序,运行到该行直接输出,不需要等待键盘操作。

    二、scanf:格式化输入,读取键盘数据存入变量

    scanf 全称 scan format。
    作用:读取标准输入(键盘 stdin)的数据,按照格式解析,保存到变量对应的内存空间。

    数据流向:键盘(stdin标准输入) → scanf → 变量内存

    scanf 的数据流向与 printf 正好相反:

    #mermaid-svg-vFcxDG9QFGrxABTE{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vFcxDG9QFGrxABTE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vFcxDG9QFGrxABTE .error-icon{fill:#552222;}#mermaid-svg-vFcxDG9QFGrxABTE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vFcxDG9QFGrxABTE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vFcxDG9QFGrxABTE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vFcxDG9QFGrxABTE .marker.cross{stroke:#333333;}#mermaid-svg-vFcxDG9QFGrxABTE svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vFcxDG9QFGrxABTE p{margin:0;}#mermaid-svg-vFcxDG9QFGrxABTE .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-vFcxDG9QFGrxABTE .cluster-label text{fill:#333;}#mermaid-svg-vFcxDG9QFGrxABTE .cluster-label span{color:#333;}#mermaid-svg-vFcxDG9QFGrxABTE .cluster-label span p{background-color:transparent;}#mermaid-svg-vFcxDG9QFGrxABTE .label text,#mermaid-svg-vFcxDG9QFGrxABTE span{fill:#333;color:#333;}#mermaid-svg-vFcxDG9QFGrxABTE .node rect,#mermaid-svg-vFcxDG9QFGrxABTE .node circle,#mermaid-svg-vFcxDG9QFGrxABTE .node ellipse,#mermaid-svg-vFcxDG9QFGrxABTE .node polygon,#mermaid-svg-vFcxDG9QFGrxABTE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vFcxDG9QFGrxABTE .rough-node .label text,#mermaid-svg-vFcxDG9QFGrxABTE .node .label text,#mermaid-svg-vFcxDG9QFGrxABTE .image-shape .label,#mermaid-svg-vFcxDG9QFGrxABTE .icon-shape .label{text-anchor:middle;}#mermaid-svg-vFcxDG9QFGrxABTE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vFcxDG9QFGrxABTE .rough-node .label,#mermaid-svg-vFcxDG9QFGrxABTE .node .label,#mermaid-svg-vFcxDG9QFGrxABTE .image-shape .label,#mermaid-svg-vFcxDG9QFGrxABTE .icon-shape .label{text-align:center;}#mermaid-svg-vFcxDG9QFGrxABTE .node.clickable{cursor:pointer;}#mermaid-svg-vFcxDG9QFGrxABTE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vFcxDG9QFGrxABTE .arrowheadPath{fill:#333333;}#mermaid-svg-vFcxDG9QFGrxABTE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vFcxDG9QFGrxABTE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vFcxDG9QFGrxABTE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vFcxDG9QFGrxABTE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vFcxDG9QFGrxABTE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vFcxDG9QFGrxABTE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vFcxDG9QFGrxABTE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vFcxDG9QFGrxABTE .cluster text{fill:#333;}#mermaid-svg-vFcxDG9QFGrxABTE .cluster span{color:#333;}#mermaid-svg-vFcxDG9QFGrxABTE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vFcxDG9QFGrxABTE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vFcxDG9QFGrxABTE rect.text{fill:none;stroke-width:0;}#mermaid-svg-vFcxDG9QFGrxABTE .icon-shape,#mermaid-svg-vFcxDG9QFGrxABTE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vFcxDG9QFGrxABTE .icon-shape p,#mermaid-svg-vFcxDG9QFGrxABTE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vFcxDG9QFGrxABTE .icon-shape .label rect,#mermaid-svg-vFcxDG9QFGrxABTE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vFcxDG9QFGrxABTE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vFcxDG9QFGrxABTE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vFcxDG9QFGrxABTE :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    键盘 stdin

    输入缓冲区

    scanf 格式化解析

    变量内存

    2.1 基础语法

    scanf("格式字符串", &变量名);

    ⚠️核心重点:
    普通变量前面必须加上取地址符 &。scanf 需要拿到变量的内存地址,才能把读取到的数据写进这块内存。

    例外:字符数组(字符串),数组名本身代表首元素地址,不要加 &。

    示例:

    #include <stdio.h>
    int main(void)
    {
    int score = 0;
    printf("请输入成绩:");
    scanf("%d", &score); // int普通变量,加&
    printf("你的成绩:%d\\n", score);

    char arr[11] = {0};
    scanf("%10s", arr); // 字符数组,不加&;%10s限制最多读10字符,防止越界
    printf("输入的字符串:%s\\n", arr);
    return 0;
    }

    执行行为:代码运行到 scanf 时,程序阻塞暂停,等待用户键盘输入,按下回车之后,才继续向下执行。用户输入会先放入输入缓冲区,scanf 再从缓冲区中解析内容。

    scanf 的阻塞执行过程如下:

    #mermaid-svg-sPjzpg39nBp7r9fs{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-sPjzpg39nBp7r9fs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sPjzpg39nBp7r9fs .error-icon{fill:#552222;}#mermaid-svg-sPjzpg39nBp7r9fs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sPjzpg39nBp7r9fs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sPjzpg39nBp7r9fs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sPjzpg39nBp7r9fs .marker.cross{stroke:#333333;}#mermaid-svg-sPjzpg39nBp7r9fs svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sPjzpg39nBp7r9fs p{margin:0;}#mermaid-svg-sPjzpg39nBp7r9fs .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-sPjzpg39nBp7r9fs .cluster-label text{fill:#333;}#mermaid-svg-sPjzpg39nBp7r9fs .cluster-label span{color:#333;}#mermaid-svg-sPjzpg39nBp7r9fs .cluster-label span p{background-color:transparent;}#mermaid-svg-sPjzpg39nBp7r9fs .label text,#mermaid-svg-sPjzpg39nBp7r9fs span{fill:#333;color:#333;}#mermaid-svg-sPjzpg39nBp7r9fs .node rect,#mermaid-svg-sPjzpg39nBp7r9fs .node circle,#mermaid-svg-sPjzpg39nBp7r9fs .node ellipse,#mermaid-svg-sPjzpg39nBp7r9fs .node polygon,#mermaid-svg-sPjzpg39nBp7r9fs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sPjzpg39nBp7r9fs .rough-node .label text,#mermaid-svg-sPjzpg39nBp7r9fs .node .label text,#mermaid-svg-sPjzpg39nBp7r9fs .image-shape .label,#mermaid-svg-sPjzpg39nBp7r9fs .icon-shape .label{text-anchor:middle;}#mermaid-svg-sPjzpg39nBp7r9fs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sPjzpg39nBp7r9fs .rough-node .label,#mermaid-svg-sPjzpg39nBp7r9fs .node .label,#mermaid-svg-sPjzpg39nBp7r9fs .image-shape .label,#mermaid-svg-sPjzpg39nBp7r9fs .icon-shape .label{text-align:center;}#mermaid-svg-sPjzpg39nBp7r9fs .node.clickable{cursor:pointer;}#mermaid-svg-sPjzpg39nBp7r9fs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sPjzpg39nBp7r9fs .arrowheadPath{fill:#333333;}#mermaid-svg-sPjzpg39nBp7r9fs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sPjzpg39nBp7r9fs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sPjzpg39nBp7r9fs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sPjzpg39nBp7r9fs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sPjzpg39nBp7r9fs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sPjzpg39nBp7r9fs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sPjzpg39nBp7r9fs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sPjzpg39nBp7r9fs .cluster text{fill:#333;}#mermaid-svg-sPjzpg39nBp7r9fs .cluster span{color:#333;}#mermaid-svg-sPjzpg39nBp7r9fs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-sPjzpg39nBp7r9fs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sPjzpg39nBp7r9fs rect.text{fill:none;stroke-width:0;}#mermaid-svg-sPjzpg39nBp7r9fs .icon-shape,#mermaid-svg-sPjzpg39nBp7r9fs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sPjzpg39nBp7r9fs .icon-shape p,#mermaid-svg-sPjzpg39nBp7r9fs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sPjzpg39nBp7r9fs .icon-shape .label rect,#mermaid-svg-sPjzpg39nBp7r9fs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sPjzpg39nBp7r9fs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sPjzpg39nBp7r9fs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sPjzpg39nBp7r9fs :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    否

    是

    执行到 scanf

    程序阻塞暂停

    用户是否输入并回车

    数据进入输入缓冲区

    按格式串解析

    写入变量内存

    继续向下执行

    2.2 scanf 的返回值(重要知识点)

    scanf 会返回一个整数:

    • 返回成功匹配读取到的数据项的个数;
    • 读取失败或者读到文件末尾,返回 EOF(一般值为 -1)。
      示例:

    #include <stdio.h>
    int main(void)
    {
    int a,b,c;
    int ret = scanf("%d %d %d", &a, &b, &c);
    printf("a = %d, b = %d, c = %d\\n", a, b, c);
    printf("ret = %d\\n", ret); // ret表示成功读取的变量个数
    return 0;
    }

    返回值经常用来做多组输入,两种经典写法:

    //写法1:成功读到2个就继续
    while (scanf("%d %d",&a,&b) == 2)
    {
    printf("%d %d\\n", a, b);
    }

    //写法2:读到EOF结束
    while (scanf("%d %d",&a,&b)!=EOF)
    {
    printf("%d %d\\n", a, b);
    }

    2.3 scanf 占位符注意点

  • %d、%f、%s 会自动跳过开头的空格、换行、制表符;唯独 %c 不会跳过空白字符,会直接读取空格、回车;
    • 如果要在读取字符的同时跳过前置空白,写法为:scanf(" %c", &ch);(%c 前面写一个空格);
  • %f 用于读取 float;%lf 用于读取 double;
  • %s 读到空格就停止,不能读取带空格的字符串;
  • 赋值忽略符 %*c:* 代表读取数据但不保存,可以用来跳过分隔符,例如处理 2025-10-01 这种带分隔符的输入:
  • int year,month,day;
    scanf("%d%*c%d%*c%d", &year, &month, &day);

    2.4 VS 编译器特殊警告说明

    在 VS 环境直接写标准 scanf,会报 C6031 警告,提示该函数不安全。

    临时解决:在 .c 文件最顶部添加宏定义:

    #define _CRT_SECURE_NO_WARNINGS 1
    #include <stdio.h>

    ⚠️ 注意:scanf_s 是微软 VS 独有的扩展函数,不是 C 语言标准库函数,GCC、Clang 等其他编译器并不识别,初学阶段优先使用标准 scanf。

    一劳永逸地永久配置 VS:

  • VS 创建 .c/.cpp 文件本质是拷贝模板文件:newc++file.cpp;
  • 在这个模板文件最顶部写上 #define _CRT_SECURE_NO_WARNINGS 1;
  • 以后新建的代码文件自动带上这句宏;查找文件可以使用 Everything 工具。
    键盘输入 → scanf →【变量内存】→ printf → 屏幕输出
  • printf 与 scanf 的协作关系,可以用下面这张图概括:

    #mermaid-svg-2Uxh4dRwlEv1jHfX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2Uxh4dRwlEv1jHfX .error-icon{fill:#552222;}#mermaid-svg-2Uxh4dRwlEv1jHfX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2Uxh4dRwlEv1jHfX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .marker.cross{stroke:#333333;}#mermaid-svg-2Uxh4dRwlEv1jHfX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2Uxh4dRwlEv1jHfX p{margin:0;}#mermaid-svg-2Uxh4dRwlEv1jHfX .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster-label text{fill:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster-label span{color:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster-label span p{background-color:transparent;}#mermaid-svg-2Uxh4dRwlEv1jHfX .label text,#mermaid-svg-2Uxh4dRwlEv1jHfX span{fill:#333;color:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .node rect,#mermaid-svg-2Uxh4dRwlEv1jHfX .node circle,#mermaid-svg-2Uxh4dRwlEv1jHfX .node ellipse,#mermaid-svg-2Uxh4dRwlEv1jHfX .node polygon,#mermaid-svg-2Uxh4dRwlEv1jHfX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .rough-node .label text,#mermaid-svg-2Uxh4dRwlEv1jHfX .node .label text,#mermaid-svg-2Uxh4dRwlEv1jHfX .image-shape .label,#mermaid-svg-2Uxh4dRwlEv1jHfX .icon-shape .label{text-anchor:middle;}#mermaid-svg-2Uxh4dRwlEv1jHfX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .rough-node .label,#mermaid-svg-2Uxh4dRwlEv1jHfX .node .label,#mermaid-svg-2Uxh4dRwlEv1jHfX .image-shape .label,#mermaid-svg-2Uxh4dRwlEv1jHfX .icon-shape .label{text-align:center;}#mermaid-svg-2Uxh4dRwlEv1jHfX .node.clickable{cursor:pointer;}#mermaid-svg-2Uxh4dRwlEv1jHfX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .arrowheadPath{fill:#333333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2Uxh4dRwlEv1jHfX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2Uxh4dRwlEv1jHfX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2Uxh4dRwlEv1jHfX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster text{fill:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX .cluster span{color:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2Uxh4dRwlEv1jHfX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2Uxh4dRwlEv1jHfX rect.text{fill:none;stroke-width:0;}#mermaid-svg-2Uxh4dRwlEv1jHfX .icon-shape,#mermaid-svg-2Uxh4dRwlEv1jHfX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2Uxh4dRwlEv1jHfX .icon-shape p,#mermaid-svg-2Uxh4dRwlEv1jHfX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2Uxh4dRwlEv1jHfX .icon-shape .label rect,#mermaid-svg-2Uxh4dRwlEv1jHfX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2Uxh4dRwlEv1jHfX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2Uxh4dRwlEv1jHfX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2Uxh4dRwlEv1jHfX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    输出交互提示

    键盘 stdin

    scanf

    变量内存数据中转站

    printf

    屏幕 stdout

    >
    scanf 负责把输入写入变量内存;printf 仅仅读取变量内存的值进行打印。两个函数互相不知道对方的存在。。

    2. **二者完全可以单独使用,不强制成对**

    // 只使用printf:不需要用户输入,直接输出文本
    printf(“Hello C语言\\n”);

    // 只使用scanf:程序等待输入,无任何提示,实际开发不推荐
    int a;
    scanf(“%d”, &a);3. 为什么教程示例总把两者写在一起?工程上的搭配逻辑是:printf 输出提示文字,告诉用户需要输入什么;scanf 接收键盘输入存入变量;后续再用 printf 打印变量,校验输入结果。

    #include <stdio.h>
    int main(void)
    {
    int num = 0;
    printf("请输入一个整数:"); // printf输出交互提示
    scanf("%d", &num); // scanf读取输入存入变量
    printf("你输入的数字是:%d\\n", num); // printf读取变量输出
    return 0;
    }

    四、初学者高频踩坑汇总

    坑 1:scanf 忘记写取地址 &

    int a;
    scanf("%d", a); // ❌错误,没有传入内存地址,程序运行崩溃
    scanf("%d", &a); // ✔正确

    坑 2:给字符数组画蛇添足加上 &

    char buf[20]={0};
    scanf("%s", &buf); // ❌数组名本身就是首元素地址,不需要&
    scanf("%s", buf); // ✔

    坑3:直接写 scanf,没有 printf 提示

    控制台一片空白,用户完全不知道该输入什么,交互体验极差。

    坑4:占位符和数据类型不匹配scanf 中读取 double 错误写 %f;printf 打印 int 用 %f,会出现乱码随机数值。。

    区分小提示:

    • printf:float、double都用%f;
    • scanf:float用%f,double必须用%lf。

    坑5:%c 读取遗留回车换行

    scanf 读取数字之后,再用 %c 读取字符,会读到缓冲区残留回车。
    解决方案:格式串内 %c 前面增加空格 scanf(" %c", &ch);。

    坑 6:VS 直接替换为 scanf_s

    scanf_s 是 MSVC 专属,不具备跨平台可移植性,初学不要盲目使用优先用宏屏蔽警告继续使用标准 scanf。。### 坑7:使用 %s 不限制长度,数组越界

    char name[11] = {0};
    scanf("%s", name); // ❌输入超过10字符,内存越界,危险
    scanf("%10s", name); // ✔限制最多读取10个字符

    五、printf 与 scanf 核心差异对比

    对比维度printfscanf
    作用 格式化输出,把内存中的常量、变量按指定格式打印到屏幕 格式化输入,把键盘读到的数据按指定格式写入变量内存
    数据流向 程序内存(变量/常量)→ printf → 屏幕(stdout) 键盘(stdin)→ scanf → 变量内存
    是否阻塞 不阻塞,执行到该行立即输出,无需等待键盘 阻塞,执行到该行暂停,等待用户输入并回车后才继续
    参数是否加 & 不加,直接传变量值(传值调用) 普通变量必须加 &;字符数组名本身即首元素地址,不加 &
    返回值含义 返回成功输出的字符个数,出错返回负数 返回成功匹配读取的数据项个数,失败或读到文件末尾返回 EOF(一般为 -1)
    %f 与 %lf 差异 float、double 都用 %f,%lf 也可用但无区别 float 用 %f,double 必须用 %lf,写错会读入错误数据
    是否自动跳过空白字符 不涉及输入,无此概念 %d、%f、%s 会自动跳过开头空白;%c 不跳过,需在格式串中写 " %c"

    要点说明:

    • 二者最本质的区别是数据流动方向相反:printf 从内存流向屏幕,scanf 从键盘流向内存,中间都依赖变量内存作为数据载体,彼此之间没有直接调用关系。
    • 参数写法上,printf 传的是变量的值,scanf 传的是变量的地址,这也是初学者最容易漏写 & 的根源。
    • 占位符并非完全通用:%f 与 %lf 在 scanf 中必须严格区分,而 %c 对空白字符的处理也是 scanf 独有的坑点,使用时需格外留意。

    五、总结

  • printf:标准输出,把内存数据打印到屏幕;scanf:标准输入,读取键盘数据写入内存变量。;2. 两个函数互不直接通信,变量内存才是数据中转站,二者不是必须成对出现。;3. scanf 记忆要点:普通变量加 &;字符数组不加 &;注意 %c 对空白字符的处理;尽量限制 %s 读取长度,避免数组越界。;4. scanf 有返回值,可以用来判断输入是否成功,常用于多组输入场景。;5. 友好交互代码流程:printf 输出提示 → scanf 接收输入 → printf 输出结果。。
  • 赞(0)
    未经允许不得转载:171主机测评 » C 语言:彻底搞懂 printf 与 scanf 的作用、数据流向以及常见误区
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址