簡體   English   中英

在 clang 中用大括號括起來的列表初始化的 char 數組中的尾隨符號是什么?

[英]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.

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