簡體   English   中英

數組初始化之間的差異

[英]Difference between Array initializations

請參閱以下聲明:

char a[5]="jgkl"; // let's call this Statement A
char *b="jhdfjnfnsfnnkjdf"; // let's call this Statement B , and yes i know this is not an Array
char c[5]={'j','g','k','l','\0'}; // let's call this Statement C

現在,陳述A和C之間有什么區別嗎? 我的意思是兩個都應該在Stack上嗎? 只有b將位於靜態位置。


那么在程序的整個生命周期中,不會使“jgkl”存在於靜態位置嗎? 既然它應該是只讀/常數? 請澄清。

不,因為語句A中的字符 “jgkl”用於初始化a ,它不會在可執行文件中為字符串創建存儲(除了通過聲明a創建的存儲)。 此聲明在讀寫內存中創建一個字符數組,其中包含字節{'j','g','k','l','\\0'} ,但是用於初始化它的字符串是否則不存在於可執行結果中。

在語句B中,字符串文字的地址用作初始化程序。 變量char *b是存儲在讀寫存儲器中的指針。 它指向字符串"jhdfjnfnsfnnkjdf" 此字符串存在於可執行映像中通常稱為“.sdata”的段中,表示“靜態數據”。 字符串通常存儲在只讀存儲器中,如C標准所允許的那樣。

這是聲明一個字符數組和一個字符串常量之間的一個關鍵區別:即使你有一個指向字符串常量的指針,你也不應該修改內容。

根據ANSI C標准第6.5.7節初始化,嘗試修改字符串常量是“未定義的行為”。

如果[]是靜態的那么c [] - 兩者是等價的,也不是字符串文字。 這兩個同樣可以被聲明,以便它們在堆棧中 - 它取決於它們的聲明位置和方式,而不是用於指定其內容的語法。

值“jgkl”可能永遠不會加載到工作內存中。 在調用main之前,運行一個函數(通常稱為cinit )。 此函數執行的操作之一是初始化靜態和文件范圍變量。 在我使用的DSP編譯器上,初始值存儲在一個表中,該表是程序映像的一部分。 表格的格式與正在初始化的變量的格式無關。 初始化程序表仍然是程序映像的一部分,永遠不會復制到RAM。 簡單地說,內存中無處可以訪問“jgkl”。

a這樣a小字符串可能根本不存儲在該表中。 優化器可以將其減少到等效(偽指令) store reg const(152<<24|167<<16|153<<8|154)

我懷疑大多數編譯器是相似的。

A和C完全相同。 A中使用的語法是C語法的縮寫。

名為ac每個對象是長度為5的字節數組,存儲在存儲器中的某個位置,該位置在執行期間是固定的。 程序可以隨時更改元素字節。 編譯器負責決定如何初始化對象。 編譯器可能生成類似於a[0] = 'j'; a[1] = 'g'; ... a[0] = 'j'; a[1] = 'g'; ... a[0] = 'j'; a[1] = 'g'; ... ,或類似於memcpy(a, static_read_only_initialization_data[1729], 5)或其選擇的任何內容。 如果聲明發生在函數中,則數組位於(概念)堆棧上;如果聲明發生在文件范圍內,則數組位於全局可寫內存中。

名為b的對象是指向字節的指針。 它的初始值是一個指向字符串文字內存的指針,它在許多具有只讀內存的實現上是只讀的,但不是全部。 b的值可能會更改(例如,指向不同的字符串,或者為NULL )。 該程序不允許更改jhdfjnfnsfnnkjdf"的內容jhdfjnfnsfnnkjdf" ,盡管在C中通常實現可能不會強制執行此操作。

C-Literals始終是只讀的。

  • a)分配5個字節的內存並存儲來自文字的內容。 '\\ 0'在里面
  • b)分配sizeof(size_t)字節的內存並將文字地址存儲在其中
  • c)分配5個字節的內存並在其中存儲5個字符值

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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