命名空間
變體
動作

printf, fprintf, sprintf, snprintf, printf_s, fprintf_s, sprintf_s, snprintf_s

出自 cppreference.com
< c‎ | io
 
 
檔案輸入/輸出
型別與物件
        
函式
檔案存取
(C95)
非格式化輸入/輸出
(C95)(C95)
(C95)
(C95)(C95)
(C95)
(C95)

格式化輸入
直接輸入/輸出
格式化輸出
printffprintfsprintfsnprintfprintf_sfprintf_ssprintf_ssnprintf_s
(C99)(C11)(C11)(C11)(C11)
檔案定位
錯誤處理
檔案操作
 
定義於標頭檔 <stdio.h>
(1)
int printf( const char*          format, ... );
(直到 C99)
int printf( const char* restrict format, ... );
(自 C99 起)
(2)
int fprintf( FILE*          stream, const char*          format, ... );
(直到 C99)
int fprintf( FILE* restrict stream, const char* restrict format, ... );
(自 C99 起)
(3)
int sprintf( char*          buffer, const char*          format, ... );
(直到 C99)
int sprintf( char* restrict buffer, const char* restrict format, ... );
(自 C99 起)
int snprintf( char* restrict buffer, size_t bufsz,
              const char* restrict format, ... );
(4) (自 C99 起)
int printf_s( const char* restrict format, ... );
(5) (自 C11 起)
int fprintf_s( FILE* restrict stream, const char* restrict format, ... );
(6) (自 C11 起)
int sprintf_s( char* restrict buffer, rsize_t bufsz,
               const char* restrict format, ... );
(7) (自 C11 起)
int snprintf_s( char* restrict buffer, rsize_t bufsz,
                const char* restrict format, ... );
(8) (自 C11 起)

從給定位置載入資料,將其轉換為字元字串等效形式,並將結果寫入各種接收器/串流

1) 將結果寫入輸出串流 stdout
2) 將結果寫入輸出串流 stream
3) 將結果寫入字元字串緩衝區 buffer。如果待寫入的字串(加上終止的空字元)超出 buffer 所指向陣列的大小,則行為是未定義的。
4) 將結果寫入字元字串緩衝區 buffer。最多寫入 bufsz - 1 個字元。除非 bufsz 為零,否則產生的字元字串將以空字元終止。如果 bufsz 為零,則不寫入任何內容,且 buffer 可以是空指標;然而,回傳值(不包括空終止字元的話,應寫入的位元組數)仍會被計算並回傳。
5-8)(1-4) 相同,但以下錯誤會在執行時期偵測到,並呼叫目前已安裝的 約束處理器 函式:
  • 轉換規範符 %n 存在於 format
  • 任何對應於 %s 的引數為空指標
  • streamformatbuffer 為空指標
  • bufsz 為零或大於 RSIZE_MAX
  • 在任何字串和字元轉換規範符中發生編碼錯誤
  • (僅限 sprintf_s),要儲存在 buffer 中的字串(包括末尾的空字元)將會超過 bufsz
如同所有邊界檢查函式一樣,printf_sfprintf_ssprintf_ssnprintf_s 僅在實作定義了 __STDC_LIB_EXT1__ 且使用者在包含 <stdio.h> 之前將 __STDC_WANT_LIB_EXT1__ 定義為整數常數 1 時,才保證可用。

目錄

[編輯] 參數

串流 - 要寫入的輸出檔案串流
緩衝區 - 指向要寫入的字元字串的指標
bufsz - 最多可寫入 bufsz - 1 個字元,外加空終止字元
format - 指向空終止位元組字串的指標,指定如何解釋資料
... - 指定要列印資料的引數。如果在 預設引數提升 後,任何引數與對應轉換規範(預期型別是提升後的型別或與提升後的型別相容的型別)所預期的型別不符,或者引數數量少於 format 所需,則行為是未定義的。如果引數數量多於 format 所需,則額外的引數會被評估但忽略。

format 字串由普通位元組字元(除了 %)組成,這些字元會不變地複製到輸出串流中,以及轉換規範。每個轉換規範都具有以下格式:

  • 開頭的 % 字元。
  • (可選) 一個或多個旗標,用於修改轉換的行為
  • -:轉換結果在欄位中靠左對齊(預設為靠右對齊)。
  • +:有符號轉換的符號總是加在轉換結果的前面(預設情況下,只有當結果為負數時才在前面加上減號)。
  • 空白:如果帶符號轉換的結果沒有以符號字元開頭,或是空的,則在結果前面加上一個空白。如果存在 + 旗標,則忽略此項。
  • #:執行轉換的替代形式。請參閱下表以了解確切效果,否則行為是未定義的。
  • 0:對於整數和浮點數轉換,使用前導零來填充欄位,而非空白字元。對於整數,如果精確度已明確指定,則忽略此項。對於其他轉換,使用此旗標會導致未定義行為。如果存在 - 旗標,則忽略此項。
  • (可選) 整數值或 *,指定最小欄位寬度。如果需要,結果會用空白字元(預設情況下)填充,靠右對齊時在左側填充,靠左對齊時在右側填充。如果使用 *,則寬度由一個額外的 int 型別引數指定,該引數出現在待轉換引數之前,以及(如果提供)精確度引數之前。如果引數的值為負數,則結果將指定 - 旗標並具有正欄位寬度(注意:這是最小寬度:值永遠不會被截斷)。
  • (可選) . 後面跟隨整數或 *,或者兩者皆無,指定轉換的精確度。如果使用 *,則精確度由一個額外的 int 型別引數指定,該引數出現在待轉換引數之前,但在(如果提供)最小欄位寬度引數之後。如果此引數的值為負數,則忽略它。如果既沒有使用數字也沒有使用 *,則精確度被視為零。請參閱下表以了解精確度的確切效果。
  • (可選) 長度修飾符,指定引數的大小(結合轉換格式規範符,它指定了相應引數的型別)。
  • 轉換格式規範符。

以下格式規範符可用:

轉換
指定符
說明 預期
引數型別
長度修飾符→ hh h none l ll j z t L
僅自 C99 起可用→
% 寫入字面值 %。完整的轉換規範必須是 %% 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A)
c

寫入單一字元

  • 引數首先被轉換為 unsigned char
  • 如果使用 l 修飾符,則引數首先被轉換為字元字串,如同使用具有 wchar_t[2] 引數的 %ls
不適用 (N/A) 不適用 (N/A)
int
wint_t
不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A)
s

寫入字元字串

  • 引數必須是一個指向字元陣列初始元素的指標。
  • 精確度指定要寫入的最大位元組數。如果未指定精確度,則寫入從開始到第一個空終止字元(但不包含該字元)的所有位元組。
  • 如果使用 l 規範符,則引數必須是一個指向 wchar_t 陣列初始元素的指標,該陣列會被轉換為 char 陣列,如同呼叫 wcrtomb 並帶有零初始化的轉換狀態。
不適用 (N/A) 不適用 (N/A)
char*
wchar_t*
不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A)
d
i

有符號整數轉換為十進位表示法 [-]dddd

  • 精確度指定要顯示的最小位數。預設精確度為 1
  • 如果轉換值和精確度都為 0,則轉換結果不會產生任何字元。
  • 對於 z 修飾符,預期引數型別是 size_t 的有符號版本。
signed char
short
int
long
long long
不適用 (N/A)
o

無符號整數轉換為八進位表示法 oooo

  • 精確度指定要顯示的最小位數。預設精確度為 1
  • 如果轉換值和精確度都為 0,則轉換結果不會產生任何字元。
  • 替代實作中,如果需要,精確度會增加以寫入一個前導零。在這種情況下,如果轉換值和精確度都為 0,則會寫入單個 0
unsigned char
unsigned short
unsigned int
unsigned long
unsigned long long
unsigned version of ptrdiff_t
不適用 (N/A)
x
X

無符號整數轉換為十六進位表示法 hhhh

  • 對於 x 轉換,使用字母 abcdef
  • 對於 X 轉換,使用字母 ABCDEF
  • 精確度指定要顯示的最小位數。預設精確度為 1
  • 如果轉換值和精確度都為 0,則轉換結果不會產生任何字元。
  • 替代實作中,如果轉換值為非零,則結果會加上字首 0x0X
不適用 (N/A)
u

無符號整數轉換為十進位表示法 dddd

  • 精確度指定要顯示的最小位數。
  • 預設精確度為 1
  • 如果轉換值和精確度都為 0,則轉換結果不會產生任何字元。
不適用 (N/A)
f
F (C99)

浮點數轉換為十進位記號,格式為 [-]ddd.ddd

  • 精確度指定小數點字元後要顯示的確切位數。
  • 預設精確度為 6
  • 替代實作中,即使沒有數字跟隨,也會寫入小數點字元。
  • 對於無限大 (infinity) 和非數值 (not-a-number) 的轉換風格,請參閱備註
不適用 (N/A) 不適用 (N/A)
double
double (C99)
不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A)
long double
e
E

浮點數轉換為十進位指數記號。

  • 對於 e 轉換風格,使用 [-]d.ddd e±dd
  • 對於 E 轉換風格,使用 [-]d.ddd E±dd
  • 指數至少包含兩位數字,僅在必要時使用更多位數字。
  • 如果值為 0,則指數也為 0
  • 精確度指定小數點字元後要顯示的確切位數。
  • 預設精確度為 6
  • 替代實作中,即使沒有數字跟隨,也會寫入小數點字元。
  • 對於無限大 (infinity) 和非數值 (not-a-number) 的轉換風格,請參閱備註
不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A)
a
A

(C99)

浮點數轉換為十六進位指數記號。

  • 對於 a 轉換風格,使用 [-] 0xh.hhh p±d
  • 對於 A 轉換風格,使用 [-] 0Xh.hhh P±d
  • 如果引數是正規化 (normalized) 浮點值,則第一個十六進位數字不是 0
  • 如果值為 0,則指數也為 0
  • 精確度指定十六進位小數點字元後要顯示的確切位數。
  • 預設精確度足以精確表示該值。
  • 替代實作中,即使沒有數字跟隨,也會寫入小數點字元。
  • 對於無限大 (infinity) 和非數值 (not-a-number) 的轉換風格,請參閱備註
不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A)
g
G

浮點數轉換為十進位或十進位指數記號,取決於值和精確度

  • 對於 g 轉換風格,將執行風格 ef 的轉換。
  • 對於 G 轉換風格,將執行風格 Ef(直到 C99)F(自 C99 起) 的轉換。
  • P 等於精確度(如果非零),如果未指定精確度則為 6,如果精確度為 0 則為 1。然後,如果以風格 E 進行的轉換將具有指數 X
    • 如果 P > X ≥ −4,則轉換將採用風格 fF(自 C99 起),且精確度為 P − 1 − X
    • 否則,轉換將採用風格 eE,且精確度為 P − 1
  • 除非請求替代表示,否則會移除尾隨零;如果沒有剩餘的小數部分,則也會移除小數點字元。
  • 對於無限大 (infinity) 和非數值 (not-a-number) 的轉換風格,請參閱備註
不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A)
n

回傳此函式呼叫到目前為止已寫入的字元數

  • 結果會寫入引數所指向的值。
  • 此規範可能不包含任何旗標欄位寬度精確度
  • 對於 z 修飾符,預期引數型別為 S*,其中 Ssize_t 的有符號版本。
signed char*
short*
int*
long*
long long*
不適用 (N/A)
p

寫入實作定義的字元序列,定義一個指標

不適用 (N/A) 不適用 (N/A)
void*
不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A) 不適用 (N/A)
備註

浮點轉換函式將無限大 (infinity) 轉換為 infinfinity。使用哪一個由實作定義。

非數值 (Not-a-number) 被轉換為 nannan(char_sequence)。使用哪一個由實作定義。

轉換 FEGA 會改為輸出 INFINFINITYNAN

用於列印 charunsigned charsigned charshortunsigned short 的轉換規範符,預期的是 預設引數提升後的提升型別,但在列印之前,其值會被轉換為 charunsigned charsigned charshortunsigned short。傳遞這些型別的值是安全的,因為在呼叫可變引數函式時會發生提升。

固定寬度字元型別 (int8_t 等) 的正確轉換規範定義在標頭檔 <inttypes.h> 中(儘管 PRIdMAXPRIuMAX 等與 %jd%ju 等是同義的)。

寫入記憶體的轉換規範符 %n 是安全漏洞的常見目標,其中格式字串取決於使用者輸入,且不被邊界檢查的 printf_s 家族函式支援(自 C11 起)

在每個轉換規範符的作用之後有一個序列點;這允許在同一變數中儲存多個 %n 結果,或者作為一個極端情況,在同一個呼叫中列印由較早的 %n 修改的字串。

如果轉換規範無效,則行為是未定義的。

[編輯] 回傳值

1,2) 傳輸到輸出串流的字元數,如果發生輸出錯誤或編碼錯誤(針對字串和字元轉換規範符),則為負值。
3) 寫入 buffer 的字元數(不計入終止空字元),如果發生編碼錯誤(針對字串和字元轉換規範符),則為負值。
4) 如果忽略 bufsz,則應寫入 buffer 的字元數(不包括終止空字元),如果發生編碼錯誤(針對字串和字元轉換規範符),則為負值。
5,6) 傳輸到輸出串流的字元數,如果發生輸出錯誤、執行時期約束違規錯誤或編碼錯誤,則為負值。
7) 寫入 buffer 的字元數,不計入空字元(只要 buffer 不是空指標,且 bufsz 不為零且不大於 RSIZE_MAX,則空字元總是會被寫入),或在執行時期約束違規時為零,在編碼錯誤時為負值。
8) 字元數(不包括終止空字元,只要 buffer 不是空指標,且 bufsz 不為零且不大於 RSIZE_MAX,則空字元總是會被寫入),如果忽略 bufsz,則應寫入 buffer;如果在執行時期約束違規或編碼錯誤發生時,則為負值。

[編輯] 備註

C 標準和 POSIX 指定,當引數與目標緩衝區重疊時,sprintf 及其變體的行為是未定義的。範例:

sprintf(dst, "%s and %s", dst, t); // <- broken: undefined behavior

POSIX 指定,在錯誤發生時會設定 errno。它還指定了額外的轉換規範,最值得注意的是支援引數重新排序(在 % 之後立即加上 n$ 表示第 n 個引數)。

呼叫 snprintf 時,將 bufsz 設為零,並將 buffer 設為空指標,有助於確定包含輸出所需的緩衝區大小。

const char fmt[] = "sqrt(2) = %f";
int sz = snprintf(NULL, 0, fmt, sqrt(2));
char buf[sz + 1]; // note +1 for terminating null byte
snprintf(buf, sizeof buf, fmt, sqrt(2));

snprintf_ssnprintf 相似,但與 sprintf_s 不同,它會截斷輸出以符合 bufsz - 1

[編輯] 範例

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
 
int main(void)
{
    const char* s = "Hello";
    printf("Strings:\n"); // same as puts("Strings");
    printf(" padding:\n");
    printf("\t[%10s]\n", s);
    printf("\t[%-10s]\n", s);
    printf("\t[%*s]\n", 10, s);
    printf(" truncating:\n");
    printf("\t%.4s\n", s);
    printf("\t%.*s\n", 3, s);
 
    printf("Characters:\t%c %%\n", 'A');
 
    printf("Integers:\n");
    printf("\tDecimal:\t%i %d %.6i %i %.0i %+i %i\n",
                         1, 2,   3, 0,   0,  4,-4);
    printf("\tHexadecimal:\t%x %x %X %#x\n", 5, 10, 10, 6);
    printf("\tOctal:\t\t%o %#o %#o\n", 10, 10, 4);
 
    printf("Floating-point:\n");
    printf("\tRounding:\t%f %.0f %.32f\n", 1.5, 1.5, 1.3);
    printf("\tPadding:\t%05.2f %.2f %5.2f\n", 1.5, 1.5, 1.5);
    printf("\tScientific:\t%E %e\n", 1.5, 1.5);
    printf("\tHexadecimal:\t%a %A\n", 1.5, 1.5);
    printf("\tSpecial values:\t0/0=%g 1/0=%g\n", 0.0 / 0.0, 1.0 / 0.0);
 
    printf("Fixed-width types:\n");
    printf("\tLargest 32-bit value is %" PRIu32 " or %#" PRIx32 "\n",
                                     UINT32_MAX,     UINT32_MAX );
}

可能輸出

Strings:
 padding:
        [     Hello]
        [Hello     ]
        [     Hello]
 truncating:
        Hell
        Hel
Characters:     A %
Integers:
        Decimal:        1 2 000003 0  +4 -4
        Hexadecimal:    5 a A 0x6
        Octal:          12 012 04
Floating-point:
        Rounding:       1.500000 2 1.30000000000000004440892098500626
        Padding:        01.50 1.50  1.50
        Scientific:     1.500000E+00 1.500000e+00
        Hexadecimal:    0x1.8p+0 0X1.8P+0
        Special values: 0/0=-nan 1/0=inf
Fixed-width types:
        Largest 32-bit value is 4294967295 or 0xffffffff

[編輯] 參考文獻

  • C23 標準 (ISO/IEC 9899:2024)
  • 7.21.6.1 fprintf 函式 (p: TBD)
  • 7.21.6.3 printf 函式 (p: TBD)
  • 7.21.6.5 snprintf 函式 (p: TBD)
  • 7.21.6.6 sprintf 函式 (p: TBD)
  • K.3.5.3.1 fprintf_s 函式 (p: TBD)
  • K.3.5.3.3 printf_s 函式 (p: TBD)
  • K.3.5.3.5 snprintf_s 函式 (p: TBD)
  • K.3.5.3.6 sprintf_s 函式 (p: TBD)
  • C17 標準 (ISO/IEC 9899:2018)
  • 7.21.6.1 fprintf 函式 (p: 225-230)
  • 7.21.6.3 printf 函式 (p: 236)
  • 7.21.6.5 snprintf 函式 (p: 237)
  • 7.21.6.6 sprintf 函式 (p: 237)
  • K.3.5.3.1 fprintf_s 函式 (p: 430)
  • K.3.5.3.3 printf_s 函式 (p: 432)
  • K.3.5.3.5 snprintf_s 函式 (p: 432-433)
  • K.3.5.3.6 sprintf_s 函式 (p: 433)
  • C11 標準 (ISO/IEC 9899:2011)
  • 7.21.6.1 fprintf 函式 (p: 309-316)
  • 7.21.6.3 printf 函式 (p: 324)
  • 7.21.6.5 snprintf 函式 (p: 325)
  • 7.21.6.6 sprintf 函式 (p: 325-326)
  • K.3.5.3.1 fprintf_s 函式 (p: 591)
  • K.3.5.3.3 printf_s 函式 (p: 593-594)
  • K.3.5.3.5 snprintf_s 函式 (p: 594-595)
  • K.3.5.3.6 sprintf_s 函式 (p: 595-596)
  • C99 標準 (ISO/IEC 9899:1999)
  • 7.19.6.1 fprintf 函式 (p: 274-282)
  • 7.19.6.3 printf 函式 (p: 290)
  • 7.19.6.5 snprintf 函式 (p: 290-291)
  • 7.19.6.6 sprintf 函式 (p: 291)
  • C89/C90 標準 (ISO/IEC 9899:1990)
  • 4.9.6.1 fprintf 函式
  • 4.9.6.3 printf 函式
  • 4.9.6.5 sprintf 函式

[編輯] 另請參閱

將格式化的寬字元輸出列印到 stdout、檔案串流或緩衝區
(函式) [編輯]
將格式化的輸出列印到 stdout、檔案串流或緩衝區
使用可變引數列表
(函式) [編輯]
將字元字串寫入檔案串流
(函式) [編輯]
stdin、檔案串流或緩衝區讀取格式化輸入
(函式) [編輯]
C++ 文件 關於 printf, fprintf, sprintf, snprintf
English Deutsch 日本語 中文(简体) 中文(繁體)