簡體   English   中英

C編程中的字符串混淆

[英]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為止,所允許的只是三個元素)。 在我的情況下, \\0l (笑臉)之后出現了一個元素,而在您的情況下,它恰好在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.

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