[英]What's the trailing symbols within an char array which initialized with brace-enclosed lists in clang?
#include <stdio.h>
int main(int argc, const char *argv[]) {
char name1[] = {'f','o','o'};
char name2[] = "foo";
printf("%s\n", name1);
printf("%s\n", name2);
return 0;
}
運行上面的代碼會導致:
foox\363\277\357\376
foo
Program ended with exit code: 0
那么,這兩個初始化器有什么區別呢?
name1
是一個由三個字符組成的數組{'f', 'o', 'o'}
。
name2
是一個由四個字符組成的數組{'f', 'o', 'o', '\0'}
。
printf("%s", ...)
需要一個以 null 字符結尾的數組。 因為name1
不是,所以您開始取消引用超出數組末尾的字符,這可能具有傳統的未定義行為。
第一個數組(即{'f','o','o'}
)將沒有null
字符'\0'
,而第二個數組(即"foo"
)將。
使用%s
時的printf規范說明如下:
如果不存在 l 修飾符: const char * 參數應為指向字符類型數組的指針(指向字符串的指針)。 數組中的字符最多寫入(但不包括)一個終止 null 字節('\0'); 如果指定了精度,則寫入的數量不超過指定的數量。 如果給定精度,則不需要存在 null 字節; 如果未指定精度或大於數組的大小,則數組必須包含終止 null 字節。
由於您的printf
不包括精度,因此它將寫入數組中的字符,直到到達 null 字節( '\0'
)。 因此,對於char name1[] = {'f','o','o'};
導致 printf 從分配給name1數組的 memory 中寫入字符。 這種行為被認為是未定義的。
這就是為什么printf("%s\n", name1);
從 memory 中不應該訪問的下一個位置打印foo加上一些額外的符號,而printf("%s\n", name2);
它按原樣打印字符串“ foo"
。
數組中沒有尾隨符號。
但是printf
的%s
格式需要一個string ,而數組name1
不是一個字符串:根據定義, C 字符串是零終止的……而您的數組不是。 因此,行為是未定義的,在您的特定情況下似乎發生的情況是printf
繼續打印恰好位於 memory 內容后面的隨機值name1
。
在 C 語言中,如果您使用逐字符初始化程序初始化字符串,則需要輸入'\0'
,它是 NULL/終止字符以指示字符串的結尾。 所以 name1 應該是{'f', 'o', 'o', '\0'}
您可以在 output 的末尾看到的x\363\277\357\376
只是因為 printf 在字符串名稱的末尾找不到“\0”而打印的垃圾值1。
對於 name2,您使用雙引號來初始化字符串,該字符串會自動在字符串末尾放置一個'\0'
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.