首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C語言printf格式化輸出完全指南:格式符、標志、寬度、精度與長度修飾符

     編輯:關於C

printf族函數是C語言最核心的格式化輸出工具。本文系統梳理格式字符串語法、所有格式轉換符、標志字符、寬度精度控制、長度修飾符,並通過示例演示輸出效果與常見陷阱。

格式字符串語法結構


%[標志][最小寬度][.精度][長度]類型

方括號內為可選項,類型為必選。

類型轉換符(核心)

符號輸出類型說明
d / i有符號十進制整數d為十進制,i兼容八/十六進制輸入(scanf),輸出同d
u無符號十進制整數
o八進制無符號整數不輸出前綴0
x / X十六進制無符號整數x輸出a-f,X輸出A-F,不輸出前綴0x
f / F十進制浮點數固定小數點記法,f輸出nan/inf,F輸出NAN/INF
e / E科學記數法浮點數e輸出e+nn,E輸出E+NN,總有一位小數點前數字
g / G自動選擇f或e按較短輸出,去除尾部0,精度指有效數字總數
a / A十六進制浮點數C99,精確表示二進制浮點值,如0x1.921fb54442d18p+1
c單個字符對應int參數,輸出對應字符
s字符串對應char*,輸出至\0,精度限最大字符數
p指針地址實現定義格式,通常0x前綴十六進制
n不輸出將已輸出字符數寫入對應int*參數,極少用
%字面%%%輸出單個%

標志字符

標志作用適用類型
-左對齊(默認右對齊),右側填空格所有
+有符號類型總顯示符號(+或-)d,i,f,e,g等
空格正數前加空格,負數前加-(+優先)有符號數值
#替代形式:o加前綴0,x/X加0x/0X,f/e/g強制顯示小數點,g/G保留尾部0o,x,X,f,e,g
0右對齊時左側填0而非空格(-優先,精度指定時忽略)數值類型

最小寬度

  • 十進制整數指定最小輸出字符數
  • 實際長度超過寬度 → 按實際長度輸出(不截斷)
  • 實際長度不足 → 左側填空格(或0標志填0)
  • 可用*動態指定:printf("%*d", width, val)

精度

  • 以.開頭後跟十進制整數或*
  • 數值類型:小數點後位數(f/F/e/E),或有效數字總數(g/G)
  • 字符串:最大輸出字符數(截斷超出部分)
  • 整數:最小數字位數(不足左側填0),%.4d對12輸出0012
  • 默認精度:f/e為6,g為1,s無限制

長度修飾符

修飾符含義適用類型
hhsigned char / unsigned chard,i,o,u,x,X,n
hshort / unsigned shortd,i,o,u,x,X,n
l (ell)long / unsigned long / wchar_t / double(for f)d,i,o,u,x,X,n / c,s / f,e,g
ll (ell-ell)long long / unsigned long longd,i,o,u,x,X,n
jintmax_t / uintmax_td,i,o,u,x,X,n
zsize_t / ssize_td,i,o,u,x,X,n
tptrdiff_td,i,o,u,x,X,n
Llong doublef,e,g,a

關鍵:%lf在printf中等同%f(float傳參自動提升為double),但在scanf中%lf對應double*,%f對應float*。

綜合示例演示


#include <stdio.h>

int main() {
    int a = 15;
    float b = 138.3576278f;
    double c = 35648256.3645687;
    char d = 'p';
    
    printf("a=%d,%5d,%o,%x\n", a, a, a, a);
    // a=15,   15,17,f
    
    printf("b=%f,%.4f,%e,%10.4f\n", b, b, b, b);
    // b=138.357628,138.3576,1.383576e+02,  138.3576
    
    printf("c=%lf,%f,%8.4lf\n", c, c, c);
    // c=35648256.364569,35648256.364569,35648256.3646
    
    printf("d=%c,%8c\n", d, d);
    // d=p,       p
    
    return 0;
}

參數求值順序陷阱(重點)

C標準未規定函數參數求值順序。printf的可變參數求值順序由編譯器決定(通常右到左,但不可依賴)。


int i = 8;
printf("%d\n%d\n%d\n%d\n%d\n", ++i, --i, i--, i++, -i--);
// 輸出不可預期!屬於未定義行為(同一表達式多次修改i且無序列點)

鐵律:絕不在同一printf調用中對同一變量既修改又讀取。若需連續輸出變化值,分多條語句:


int i = 8;
printf("%d\n", ++i); // 9
printf("%d\n", i++); // 9
printf("%d\n", i);   // 10

安全性與最佳實踐

問題風險對策
格式字符串漏洞用戶輸入作格式串 → 內存讀寫攻擊永遠用字面量格式串:printf(fmt, ...)禁用,改printf("%s", fmt)
參數類型不匹配未定義行為,崩潰或輸出亂碼啟用-Wformat -Wformat-security,C++用iostreams或fmt庫
緩衝區溢出sprintf無長度限制永遠用snprintf
%n 攻擊配合格式串漏洞任意寫內存禁用%n,編譯器可-Wno-format-nonliteral排查

現代替代方案

  • C++ iostreams:類型安全、可擴展、但性能較低(關閉同步後可接受)
  • fmt 庫 (C++20 std::format):fmt::print("{:0>5}", 42) → 00042,Python風格語法、類型安全、高性能、編譯期檢查
  • C++20 std::format:標準化fmt,std::format("{:.2f}", 3.14159)

精通printf格式化語法是C程序員必備基本功,但現代項目應優先遷移至類型安全的格式化庫,從根源消除格式字符串漏洞與類型不匹配風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved