[英]Confusion on strings in C programming
所以我正在學習使用編譯器Dev C ++編程c。 問題1:
#include <stdio.h>
#include <conio.h> //for the getch() function
#include <string.h>
int main(void)
{
char line[3];
strcpy(line, "Hello world");
printf("%s", line);
getch();
}
輸出:Hello world
當我聲明我的字符串僅包含3個字符時,為什么它顯示所有“ Hello world”?
問題2:
char line[3] = "Hello world";
printf("%s", line);
輸出:Hel
為什么顯示“ Hel”? 由於line [0] = H,line [1] = e和line [2] ='\\ 0',它不應該只顯示“ He”嗎? 並且%s通過搜索'\\ 0'起作用嗎?
請幫助我了解實際情況。 謝謝!
請幫助我了解實際情況。
不確定的行為!
執行此操作時, 緩沖區溢出 :
char line[3];
strcpy(line, "Hello world");
當我聲明我的字符串僅包含3個字符時,為什么它顯示所有“ Hello world”?
您正在復制的內容超出了分配的數組的大小。 這是未定義的行為,因此任何輸出都是可能的,包括但不限於,呼叫Tilda姨媽,格式化硬盤等。:) 有關更多信息, 請參見此處 。
char line[3] = "Hello world";
printf("%s", line);
在這里,您有一個緩沖區超讀 ! 請參閱alk的答案 ,為什么只有3個字符會被復制到line
。
為什么顯示“ Hel”? 它不應該只顯示“ He”
不,它又可以顯示任何內容,同樣是由於行為不確定。 查看我在計算機上得到的輸出:
海爾
這是未定義的行為,因為printf
希望您有一個以空值結尾的字符串,是的,但這並不意味着您可以訪問超出數組大小的內存,即您在內存中擁有這樣的數組
[0] [1] [2] ----------------------------------------------- . . . █ | █ | █ | H | e | l | █ | █ | █ | . . . ----------------------------------------------- <-- line --->
上面寫為█的任何東西都是未知值,不在您的權力之下,因此訪問它們是不確定的。 但是, printf
%s
期望以空字符結尾的字符串,因此,在您的命令下,它讀取的內容超出了所允許的范圍(直到l
為止,所允許的只是三個元素)。 在我的情況下, \\0
在l
(笑臉)之后出現了一個元素,而在您的情況下,它恰好在l
之后出現,因此只是靠運氣,它很可能以后會出現1000個元素。
如果您真的要打印不以null終止的char
數組,但只能打印到允許的限制,則可以執行其中之一而不會遇到任何未定義的行為。
printf("%.3s", line); // length specified at compile-time
printf("%.*s", 3, line); // length fed at run-time
提及問題2:
當使用“字符串”字面量作為初始化程序時,僅在有空間的情況下應用0
終止符。
從C99-Standard :
6.7.8初始化
[...]
14字符類型數組可以由字符串文字初始化,並可選地用大括號括起來。 字符串文字的連續字符(如果有空間或數組大小未知,則包括終止空字符)將初始化數組的元素。
這兩個程序示例均具有未定義的行為。 在第一個示例中,您將覆蓋數組之外的內存。 在第二個示例中,C不允許使用超出對象可以接受的數量的初始化程序。
2初始化程序不得嘗試為未包含在正在初始化的實體內的對象提供值。
唯一的排除是針對允許忽略終止零的字符數組進行的
14字符類型的數組可以由字符串文字或UTF-8字符串文字初始化,並可選地用大括號括起來。 字符串文字的連續字節(如果有空間或數組大小未知,則包括終止空字符)將初始化數組的元素。
因此,不應編譯第二個代碼片段,或者至少編譯器應發出診斷消息。
當我聲明我的字符串僅包含3個字符時,為什么它顯示所有“ Hello world”?
因為printf()
讀取的字符串最多為空終止符。 它不知道存儲空間有多大, strcpy()
也不知道; 如果要確保副本不超過存儲空間的長度,請使用strncpy()
(注意中間的n
)。
為什么顯示“ Hel”?
不必對此進行解釋,因為您已經溢出了緩沖區-這可能會對程序產生任何奇怪的結果。 您可能已經覆蓋了其他內容(相反,您的數據隨后可能會被覆蓋)。 如果您違反規則,則很可能會調用“未定義的行為”。
在這種情況下,由於初始化的形式,編譯器可能只寫了3個字符,但這並不是值得指望的事情-違反規則並不一定要遵循規則。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.