char a 和char a的比較

2022-05-24 08:06:10 字數 3728 閱讀 1471

指標和陣列存在著一些本質的區別。當然,在某種情況下,比如陣列作為函式的引數進行傳遞時,由於該陣列自動退化為同型別的指標,所以在函式內部,作 為函式引數傳遞進來的指標與陣列確實具有一定的一致性,但這只是一種比較特殊的情況而已,在本質上,兩者是有區別的。請看以下的例子:

char a = "1234567";

char *p = "1234567";

上述兩個變數的記憶體布局分別如下:

陣列a需要在記憶體中占用8個位元組的空間,這段記憶體區通過名字a來標誌。指標p則需要4個位元組的空間來存放位址,這4個位元組用名字p來標誌。其中存放的位址幾乎可以指向任何地方,也可以**都不指,即空指標。目前這個p指向某地連續的8個位元組,即字串"1234567"。

另外,例 如:對於a[2]和p[2],二者都返回字元『i』,但是編譯器產生的執行**卻不一樣。對於a[2],執行**是從a的位置開始,向後移動2兩個位元組, 然後取出其中的字元。對於p[2],執行**是從p的位置取出乙個位址,在其上加2,然後取出對應記憶體中的字元。

p指標變數本身在棧上,指向的內容在靜態儲存區;

a只是個陣列名,本身不佔執行時程式的空間,只是在源程式中用來標記乙個字元陣列(即其首位址),而陣列也是儲存在棧上的。

char s1 = "a";

char *s2 = "b";

a是在執行時刻賦值的;

而b是在編譯時就確定的;

但是,在以後的訪問中,在棧上的陣列比指標所指向的字串(例如堆)快。

比如:int main()

char a = 1;

char c = "1234567890";

char *p ="1234567890";

a = c[1];

a = p[1];

return 0;

對應的彙編**

10: a = c[1];

00401067 8a 4d f1 mov cl,byte ptr [ebp-0fh]

0040106a 88 4d fc mov byte ptr [ebp-4],cl

11: a = p[1];

0040106d 8b 55 ec mov edx,dword ptr [ebp-14h]

00401070 8a 42 01 mov al,byte ptr [edx+1]

00401073 88 45 fc mov byte ptr [ebp-4],al

第一種在讀取時直接就把字串中的元素讀到暫存器cl中,而第二種則要先把指標值讀到edx中,在根據edx讀取字元,顯然慢了。

#include

#include

char *function1()

char *function2()

char a="cdefgh";

/*這個是常量字串的拷貝,

相當於strcpy(a,"cdefgh"),

這樣寫都會有字串拷貝,

造成時間和空間上的開銷,

如果字串很長盡量不要這樣寫,

由於字元陣列a在棧上,

所以在函式結束後它便無效了..

---------------

char *a="cdefgh";

a直接指向常量字串,

這個字串儲存在靜態儲存區中...

所以在函式結束後,它返回的位址仍然有效..

*/int  main()

/*(1)function1()的a和function2()的a都是自動變數,都在棧上分配空間

(2)function1()的a分配的空間=sizeof(char *)=sizeof(void *),

任何指標的大小都是相同的,指向靜態資料區存的"cdefgh"

(3)function2()的a分配的空間=strlen("cdefgh")+1,並且用來儲存"cdefgh"

(4)返回的指標,function1指向靜態資料區,function1指向棧(已自動釋放)

故function1的值是對的

*/(1)指標陣列: 是陣列,但陣列中的每個元素都是指標

int *p[5];//如p[2]是指標,可*p[ 2]=3;

(2)指向陣列的指標: 是個指標,但它指向的是乙個陣列

int a[5];

int (*p)[5];//與前一行比較,*p相當於a,即p=&a;就像:int m;int *pm;//*pm就相當於m.pm=&m;

p= &a;//可與前一行合併為int (*p)[5]=&a;

----------------------

a代表這個陣列,它是乙個指標,指向第乙個元素

這裡一定要記住,a是陣列名,&a代表的不是取a這個變數的位址,而是取陣列元素的位址

---------------------------------------

a     的型別是 int[5]       陣列

&a    的型別是 int(*)[5]    指標——指向int[5]陣列的指標

&a[0] 的型別是 int *         指標——指向int型別的指標。

sizeof(a)=20;

sizeof(*a)=4 =sizeof(a[0]);

sizeof(*&a)=20;//因為p=&a,所以=sizeof(*p),而*p=a,所以=sizeof(a)=20;

---------------------------------------

int a[5]=;

int *ptr=(int *)(&a+1);

printf("%d,%d",*(a+1),*(ptr-1));//輸出:2,5

*pc與int

*pi,sizeof(pc)=sizeof(pi)=4,但為什麼輸出時,cout<<*pc只從記憶體處取乙個字元,而cout<&

lt;*pi則從記憶體處取4個字元,這是由指標型別(char,int)決定的.對a* p;p+1=(a*)(p的位址值+sizeof(a)),如pc+1=pc+sizeof(char)=(char*)(pc的位址值+1個位元組),而pi+1=pc+sizeof(int)=(int*)(pi的位址值+4個位元組).

對**中的&a+1,&a是陣列指標,其型別為int

(*)[5],因為p=&a,也即是p的型別.所以&a+1=&a+sizeof(a),其中a為int[5]:(把

a=int[5]代入a*

a[5]),&a+1仍是int (*)[5]型別,經(int

*)(&a+1)強制轉化為int*,賦值給ptr.後面的ptr-1=ptr-sizeof(int)=ptr的位址值-4個位元組,即變為陣列

a的最後乙個元素的位址&a[4],*(ptr-1)即為a[4],故輸出為5.

而a+1=a+sizeof(int):(此處a退化為int*,故對於a* p,a為int)=a的位址值+4個位元組,即是&a[1],則*(a+1)即a[1],故輸出2.

又如:double t= ;

double *pt= &t[3];//指向值為111

int *ptint= reinterpret_cast< int * > (pt);

char *ptch= reinterpret_cast< char * > (pt);

cout<< *( pt- 1)<< "\t"<< *(reinterpret_cast(ptint-2))<<"\t"<<

*(reinterpret_cast(ptch-8));//最後輸出結果全為578

---------------------

void fun( int *p)與void fun( int p)是一樣的,即函式列表中的陣列此時退化成了指標

char a 和char a 的區別

char a hello 中的a是指向第乙個字元 a 的乙個指標 char a 20 hello 中陣列名a也是執行陣列第乙個字元 h 的指標 但二者並不相同 看例項 把兩個字串相加 結果 對比 結果 把字串加到指標所指的字串上去,出現段錯誤,本質原因 d 0123456789 存放在常量區,是無法...

char a 和char a 的不同

char a dghtql 中的a是乙個常量指標,指向 dghtql 這個字串,並且不能通過操作指標a來改變 dghtql 存放於常量區,只能通過指標來訪問,不能通過指標來修改和賦值。如scanf 等方法不能用於a上。而char a dghtql 中的a既是陣列名又是指向第乙個字母d的指標,陣列是存...

char a 與char a 的區別

char a hello 中的a是指向第乙個字元 a 的乙個指標 char a 20 hello 中陣列名a也是執行陣列第乙個字元 h 的指標 但二者並不相同 看例項 把兩個字串相加 結果 對比 結果 把字串加到指標所指的字串上去,出現段錯誤,本質原因 d 0123456789 存放在常量區,是無法...