簡體   English   中英

當我定義數組時真正發生了什么

[英]What really happen when I defined array

我編寫程序來了解數組和指針之間的區別:

#include <stdio.h>

void main()
{
    char arr [] ="hodaya",*ptr=arr;
    printf("arr=%p\n",arr);
    printf("&arr=%p\n",&arr);
    printf("ptr=%p\n",ptr); 
    printf("&ptr=%p\n",&ptr);
}

結果:

arr=0xbfd26265

&arr=0xbfd26265

ptr=0xbfd26265

&ptr=0xbfd26260

所以我讀了下面的答案:

如何將數組地址等於它在C中的值

它回答了我的大多數問題,我只剩下一個問題!

我了解,當我定義指針時,我定義了(在特定地址中)用於保持地址的空間,因此我可以采用這樣的指針地址: &ptr

但是,當我定義數組時會發生什么?

首先,除非您的編譯器文檔明確列出void main()作為main函數的有效簽名,否則請使用int main(void) 在大多數情況下, 應該main返回一個值到運行時環境(即使只是EXIT_SUCCESS)。

所以我們來談談宣言

char arr [] ="hodaya";

"hodaya"字符串文字 它存儲為7個元素的char數組(6個字符加0的終止符),以便在程序啟動時進行分配並保持到程序退出。 字符串文字不是可修改的,嘗試更新一個字符串會導致未定義的行為(這可能意味着您的代碼因訪問沖突而崩潰,無法按預期工作)。 您應該始終將字符串文字視為只讀,並且永遠不要將其傳遞給嘗試對其進行修改的函數(例如strcpystrtok等)。

arr被聲明為char數組,它將使用字符串常量"hodaya"的內容進行初始化 數組的大小取自初始化器(7)的大小。 該聲明大致等於:

char arr[7];
strcpy( arr, "hodaya" );

也可以寫成

char arr[] = {'h', 'o', 'd', 'a', 'y', 'a', 0 };

結果相同( arr初始化為字符串"hodaya" ),語法略有不同。 在這種情況下,不會創建字符串文字。

由於您聲明了arrmain本地(據說具有自動存儲持續時間 ,這意味着函數退出時將釋放內存),因此您可以通過arr[6]修改arr[0]的內容。

現在讓我們談談ptr的聲明。

除非它是sizeof或一元&運算符的操作數,或者是用於在聲明中初始化另一個數組的字符串文字,否則類型為“ T N元素數組”的表達式將被轉換(“ decay”)為類型為“指向T指針”的表達式,該表達式的值將為數組中第一個元素的地址。 結果不是左值 也就是說,它不能成為任務的目標。

這很重要,並且引起很多混亂。 arr 不是指針 ; 它不包含地址。 當編譯器在大多數情況下看到arr時,它將用其第一個元素的地址替換它,並且所得表達式的類型將為char * 但是,如果arr是一元&運算符的操作數,則不會發生替換。 表達式的相同(數組的地址與數組的第一個元素的地址相同),但是表達式的類型不同。 代替char *&arr的類型是char (*)[7] (指向char 7元素數組的指針)。

因此,在聲明中

char *ptr = arr;

arr不是一元&運算符(或任何其他運算符)的操作數,因此適用轉換規則,並且arr第一個元素的地址寫入ptr

到您完成時,您的內存看起來類似於以下內容(地址並不旨在反映任何現實世界的體系結構):

Item            Address            0x00 0x01 0x02 0x03
----            -------            ---- ---- ---- ----
"hodaya"        0x40040             'h'  'o'  'd'  'a'
                0x40044             'y'  'a'   0    ??
                  ...
arr             0x7fffb220          'h'  'o'  'd'  'a'
                0x7fffb224          'y'  'a'   0    ??
ptr             0x7fffb228         0x7f 0xff 0xb2 0x28

同樣, arrptr僅在main函數的生存ptr存在。 字符串文字"hodaya"在整個程序的生命周期中都存在。

注意:我使用gcc 4.1.2在一個SLES 10盒上編譯了上面的示例(在修復了一些問題之后),是的,即使僅用於初始化arr ,它也為.rodata的字符串文字創建了一個條目。

arr保存數組( &arr[0] )中第一個元素的地址。

在這里,您始終在讀取元素的地址,而不是值。

arr[0] = 'a', arr[1] = 'b', arr[2] = 'c', arr[3] = 0;

char *ptr = arr;
*ptr++ = 'a', *ptr++ = 'b', *ptr++ = 'c', *ptr = 0;

暫無
暫無

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

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