[英]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);
包含兩個錯誤。
格式說明符%c
期望傳遞單個字符。 我們在 C 中定義字符常量的方式是使用單引號'N'
。
通過使用雙引號"N"
,您正在使用語法糖方式C 提供表示字符串,即由字符串終止符'\0'
封閉的字符數組
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
。
'N'
這樣的字符常量具有int
類型,而在 C++ 中它們具有char
類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.