2017-10-04 125 views
0

恆定的是否定義:機制初始化數組的一個字符串用C

char arr_of_chars[] = "hello world"; 

創建一個常數字符陣列(空終止)在存儲器中某處,然後該數組中的內容複製到arr_of_chars,或它是否直接將其分配給arr_of_chars

究竟是什麼機制在這裏工作?

+0

'你好world'是在系統中的某個地方放置空終止字符串。當變量被初始化時,字符串被複制到RAM中。 – tilz0R

+1

如果變量是全局變量或靜態變量,那麼初始化也是如此,並且在運行時不會執行復制。如果變量是自動的,那麼初始化是動態的,並且在每次變量被實例化時執行。 –

+0

@TomKarzes我不相信。考慮這個:'const char a [] =「hello world」; char b [] =「hello world」;'。你有2個確切的值,即使它們是全局的或靜態的,你在.rodata節中只會有一個'hello world'的存儲器,特別是在嵌入式系統上。它將首先在運行時被複制到非const變量。 – tilz0R

回答

0

「...創建一個常數字符陣列(空終止)在存儲器中某處,而且陣列然後複製的內容,以arr_of_chars」

事實上。字符串文字"hello world"存儲在程序的.rodata部分的某處,除非編譯器設法完全將其優化(取決於您的數組的範圍)。從那裏它被複制到你的數組中。

+0

它是''一般規則中唯一的例外,因爲它複製字符串本身,而不是通常的指針:)。 –

+1

這裏根本沒有例外。這是一個初始化,而不是一個賦值。 –

+0

什麼是'.rodata'? - ) –

0

這將在常量段中創建一個以NULL結尾的字符串hello world\0

在主函數中,這個字符串將被複制到字符數組中。

讓我突出從彙編輸出的幾行,以clairfy這一點。

PUBLIC [email protected][email protected]@[email protected] 

這會創建一個公共令牌。

CONST SEGMENT 
[email protected][email protected]@[email protected] DB 'hello world', 00H 
CONST ENDS 

這將常量空終止的字符串分配給令牌。

lea rax, QWORD PTR arr_of_chars$[rbp] 
lea rcx, OFFSET FLAT:[email protected][email protected]@[email protected] 
mov rdi, rax  ; Set destination to stack location 
mov rsi, rcx  ; Set source to public token 
mov ecx, 12  ; Set counter to number of times to repeat 
rep movsb   ; Copy single byte from source to destination and increment locations 

這由字符建立源和目的地和副本字符的12倍,這是「世界你好」的長度和空終止。目標是堆棧中的一個位置,源代碼是公共令牌。

+1

如何檢查**一個**行爲的具體實現回答這個問題? –

+0

@FelixPalmen - 你說得對。我發佈的只是一個觀察。但我不確定該標準是否定義了執行此操作的方法。但是,該操作是一個正在使用字符串文字初始化的數組。所以字符串文字必須存儲在某個地方,並且必須在初始化過程中複製到數組中。 – Superman

+0

它**不是由標準指定的,這是我的觀點;)不,不是絕對必須在某處存儲字符串文字。這一切都取決於目標的二進制格式和編譯器的決定,如果這個確切的字符串文字是** only **用於初始化這個變量,它*可以*是一個有效的決定來「消除」它並把初始化數據段中的數組 - 例如:) –

1

不是由C指定的是什麼你問簡而言之,C在抽象機及其觀察行爲方面指定的。在這種情況下,這意味着所有你知道的是從字符串文字初始化的數組變量arr_of_chars

在談論段,複製等時,你已經在討論C的具體實現以及它們在做什麼。假設arr_of_chars位於文件範圍內,並且給定了知道具有數據段的二進制文件的目標機器/系統,C編譯器可以將初始化數組直接放入數據段 - 可觀察行爲與方法是運行時首先將字節複製到陣列中。

+0

沒問題。如果字符串很短,另一種初始化的可能性是使用硬件寄存器或立即數,並且取決於char數組的用法,根本不在內存中表示它。 –

0

它是c中存儲字符串的主題。

字符串可以被存儲在以下方式,

  1. 字符串作爲字符數組使用字符指針

當字符串被聲明爲字符數組

  • 字符串,將它們存儲等的其它類型的例如,如果str []是一個自動變量,則字符串將存儲在堆棧段中,如果它是全局或靜態變量,則存儲在數據段中。

    Ex。

    char str[] = "Hello_world"; 
    

    在存儲使用字符指針串的情況下,它可以通過兩種方式來完成,

    1. 在共享段只讀字符串。

      Ex。

      char *str = "Hello_World"; 
      

    在上述線「程序hello_world」被存儲在一個共享的只讀位置,但指針STR被存儲在讀 - 寫存儲器。你可以改變str以指向別的東西,但不能改變當前的值。所以這種類型的字符串應該只在我們不想在程序的後續階段修改字符串時使用。

    1. 在堆段中動態分配。

      char *str = NULL; 
      int size = 6; 
      
      str = (char *) malloc(sizeof(char)*size); 
      
      *(str+0) = 'H'; 
      *(str+1) = 'E'; 
      *(str+2) = 'L'; 
      *(str+3) = 'L'; 
      *(str+4) = 'O'; 
      *(str+5) = '\0';