printf 与 scanf 通过格式说明符(conversion specifier)指定实参的类型与输出样式。除基本的 %d、%f 外,还可使用宽度、对齐与精度等修饰符控制排版。变参函数如何解析这些说明符见变参函数一节。

格式说明符的作用

格式串中以 % 开头的说明符与后续实参一一对应(顺序与类型须匹配)。最小示例:

#include <stdio.h>

int main(void) {
    int age = 25;
    float salary = 45000.50f;
    char grade = 'A';

    printf("Age: %d\n", age);
    printf("Salary: %.2f\n", salary);
    printf("Grade: %c\n", grade);
    return 0;
}

常用说明符

字符 %c

char c;
scanf("%c", &c);
printf("The entered character: %c", c);

有符号整数 %d 与 %i

int x;
scanf("%d", &x);
printf("Printed using %%d: %d\n", x);
printf("Printed using %%i: %i", x);

%d 与 %i 用于 int 时语义相同。

无符号整数 %u

以 %u 输出负的 int 时,按无符号整型的位模式解释,可能得到很大的正数:

unsigned int var;
scanf("%u", &var);
printf("Unsigned Integer: %u\n", var);
printf("Printing -10 using %%u: %u\n", -10);

浮点 %f、%e、%E

float a = 12.67f;
printf("Using %%f: %f\n", a);
printf("Using %%e: %e\n", a);
printf("Using %%E: %E", a);

八进制 %o 与十六进制 %x / %X

int a = 67;
printf("%o\n", a);

int b = 15454;
printf("%x\n", b);
printf("%X", b);

字符串 %s

printf 的 %s 输出以 \0 结尾的字符序列;scanf 的 %s 在遇到空白字符时停止,无法一次读入含空格的整行,整行读取可使用 fgets 或扫描集。

char str[50];
scanf("%s", str);
printf("Entered String: %s", str);

指针地址 %p

int a = 10;
printf("The Memory Address of a: %p", (void*)&a);

扩展整型与浮点

格式符类型
%ld / %lilong
%lfdouble(多用于 scanf)
%Lflong double
%luunsigned long
%lld / %llilong long
%lluunsigned long long

宽度、对齐与精度

  • 数字:最小字段宽度,不足时以空格填充(默认右对齐)。
  • -:左对齐。
  • .数字:精度;对整数表示最少位数,对字符串表示最多输出字符数,对浮点表示小数位数。
#include <stdio.h>

int main(void) {
    char str[] = "online-compiler";
    printf("%20s\n", str);
    printf("%-20s\n", str);
    printf("%20.5s\n", str);
    printf("%-20.5s\n", str);
    return 0;
}

输出:

     online-compiler
online-compiler
              online
online

浮点数常用 %.nf 保留 n 位小数。

速查表

格式符含义
%c字符
%d / %i有符号整数
%u无符号整数
%ffloat(printf)
%lfdouble(scanf)
%Lflong double
%e / %E科学计数法
%g / %G在 %f 与 %e 间自动选择
%o八进制
%x / %X十六进制
%s字符串
%p指针
%ldlong
%lldlong long
%%输出字面量 %

常见错误

  • 说明符与实参类型不匹配会导致未定义行为,例如用 %d 输出 double。
  • scanf 中除字符串外,标量实参须传递地址:scanf("%d", &x)。
  • 输出字面量百分号应写 %%。
  • scanf("%s") 遇空白停止;读整行应改用 fgets 等。

本节归纳了常用格式说明符与修饰规则。下一节讨论结构体内存对齐对对象大小的影响。