簡體   English   中英

C 編程:為什么 printf 格式說明符 %s 對於數字“123”無效?

[英]C Programming: Why printf Format Specifier %s Is Invalid For The Number “123”?

我是一個 C 編程新手。

通過其他問題的答案,我可以理解“角色”一詞可能指向不同的元素; 例如字母和數字。

我將“字符串”視為字符。

然后,請看下面的幾行:

#include <stdio.h>

main()
{
    int numbers = 123;
    printf("%c%s\n", "N", numbers); 
}

當我嘗試編譯此代碼時,顯示錯誤消息並且編譯失敗。

教科書“C 編程語言”第 13 頁對 printf 格式說明符如下所述;

" %c代表字符"

%s用於字符串”。

第一個問題:

雖然 "N" 是一個字符,但為什么%c說明符無效?

第二個問題:

雖然變量“numbers”的值為“123”,但它們是數字,包含在字符中。

我認為字符等於“字符串”。

那么,“123”雖然我用了%s,但是為什么無效呢?

我知道我的代碼會起作用,如果我像下面這樣修改它們:

#include <stdio.h>

main()
{
    int numbers = 123;
    printf("%s%d\n", "N", numbers); 
}

但我想了解為什么上面的代碼無效。

"雖然"N"是一個字符,但為什么%c說明符無效?

"N"不是字符常量。 它是一個字符串文字。 'N'是一個字符常量,與%c匹配。 單引號和雙引號之間的區別很重要。

此外,說明符永遠不會無效。 只有參數類型可以。

“那么,雖然我用%s表示"123" ,但為什么無效呢?

您沒有使用"123" ,它是一個字符串文字並發出一個char * 您使用123 123是一個integer值,存儲在int numbers類型的 object 中。 對於需要類型為char *而非int的參數的%s格式說明符,不允許使用int參數。

這就是區別。

該指令

printf("%c%s\n", "N", numbers); 

包含兩個錯誤。

  1. 格式說明符%c期望傳遞單個字符。 我們在 C 中定義字符常量的方式是使用單引號'N'
    通過使用雙引號"N" ,您正在使用語法糖方式C 提供表示字符串,即由字符串終止符'\0'封閉的字符數組

  2. 123是 integer,就像您正確編寫的%d格式說明符一樣

說到最后一個錯誤,你給出了一個原創的解釋

雖然變量“numbers”的值為“123”,但它們是數字,包含在字符中。

我認為字符等於“字符串”。

那么,“123”雖然我用了%s,但是為什么無效呢?

雖然這顯然是一個錯誤的解釋,但我覺得它很有趣,值得解釋。

123是一個字符串,即一個字符序列嗎? 是的! 但它是源代碼中的一個字符串。 編譯器將解析此字符序列,識別 integer,並確保此值存儲在包含 integer 的 memory 位置中。 在大多數現代計算機中,它將轉換為0/1序列,表示 4 字節中的數字 123。

0b01111011

源代碼的角度來看, "123"不一樣嗎? 嗯,不。 數字用雙引號括起來,因此編譯器會將其解釋為實際字符串,存儲在 memory 中作為以 nul 結尾的字符序列

--------------------------
| '1' | '2' | '3' | '\0' |
--------------------------

在 memory 中,代表這些數字的 ASCII 值(假設使用 ASCII 編碼)將被存儲

-----------------------------
| 0x31 | 0x32 | 0x33 | 0x00 |
-----------------------------

我會 go 直接回答您的問題。

第一個問題:

C編程語言區分雙引號和單引號。 雙引號將創建string文字,而單引號將創建character文字。 因此,例如'N'是一個character ,而"N"是一個僅包含單個字符的string ,即 N。所以,%c 不起作用的原因是它需要一個字符,但是你重新給它字符串"N"

第二個問題:

變量numbers的值不是“123”。 使用 C 語言的表示法,“123”將是一個包含字符“1”、“2”和“3”的字符串,而變量numbers現在包含integer 123,這就是 %s 獲勝的原因t 為numbers工作。 盡管您可以將變量 123 的值轉換為如下字符串:

#include <stdio.h>

main()
{
    int numbers = 123;
    char numbers_string[4];
    sprintf(numbers_string, "%d", numbers); // conversion happens here
    printf("%s\n", numbers_string); 
}

此外,您的問題中“字符串”和“字符”這兩種類型之間似乎存在混淆。 重要的是要了解這兩種類型是不同的。 一個字符是一個單個字節,它(通常)包含你想要的字符的 ASCII 碼。 例如,字符'A' (ASCII 碼 = 65)。 但是“字符串”是字符的集合,例如"Apple" ,在 C 語言中,“字符串”通常使用char*來實現,它指向 memory 中按順序存儲字符的位置。 (這就是我使用字符數組來保存將numbers轉換為“字符串”的結果的原因)

雖然 "N" 是一個字符,但為什么 %c 說明符無效?

"N"是一個字符串,而不是單個字符 - 雙引號表示字符串文字。 'N' (單引號)將是一個字符常量1 ,所以

printf( "%c\n", 'N' );

會正常工作。 要打印"N" ,您需要使用%s轉換說明符:

printf( "%s\n", "N" );

%s轉換說明符期望其對應參數的類型為char * (指向char的指針),它會告訴printf打印從指定地址開始的字符序列,直到它看到字符串終止符。

表達式"N"的類型為“ char的 2 元素數組”( char [2] ),數組的內容是{'N', 0} 在 C 中,字符串是一系列字符值,包括用於標記字符串結尾的 0 值終止符。 字符串(包括字符串文字)存儲在字符類型的 arrays 中。

在大多數情況下,“T 的 N 元素數組”( T T [N] )類型的表達式將被轉換(“衰減”)為“指向T的指針”( T * )類型的表達式和表達式的值將是數組第一個元素的地址。

在上面的printf語句中,表達式"N"char [2]類型轉換為char * ,表達式的值是第一個字符的地址。

雖然變量“numbers”的值為“123”,但它們是數字,包含在字符中。

讓我們看一下numbers的聲明:

int numbers = 123;

首先, numbers變量的類型int ,而不是char * 它包含什么值並不重要,它不是%s期望的類型。 其次, 123不是字符串 - 它沒有被引號包圍。 相反,它是一個integer常數。

numbers不是字符串 - 它不是存儲字符串的正確類型,並且它不包含帶有 0 終止符的字符序列。 它是一個 integer,存儲十進制值123的二進制表示。 要將其打印出來(即,在 output 設備上生成 integer 值的文本表示形式),您可以使用%d%i


  1. 在 C 中,像'N'這樣的字符常量具有int類型,而在 C++ 中它們具有char類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM