char a[]和char *a的比較,數組名,數組首地址,a,a,a[0]

char a[]和char *a的比較

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

?

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<stdio.h>
#include<stdlib.h>
char *function1()
{
???? char *a="cdefgh";//在靜態存儲區分配,一直到程序結束
???? return a;
}

char *function2()
{
???? char a[]="cdefgh";//在棧中分配,函數結束時釋放
???? return a;
}
char a[]="cdefgh";
/*這個是常量字串的拷貝,
相當於strcpy(a,"cdefgh"),
這樣寫都會有字串拷貝,
造成時間和空間上的開銷,
如果字串很長儘量不要這樣寫,
由於字元陣列a在棧上,
所以在函數結束後它便無效了..
---------------
char *a="cdefgh";
a直接指向常量字串,
這個字串保存在靜態存儲區中...
所以在函數結束後,它返回的位址仍然有效..
*/
int? main()
{
??? char test[]="123";
??? test[0]='a';//可以修改數組內部元素的值
??? char* test1="456";
??? *test1='7';//test1不可以修改,是const char*的類型的值
??? /*char *a="cdefgh";
??? 此時a為const char*,
??? 也就是說你不能改變*a的值。
??? char a[]="cdefgh";你可以通過a[i]改變它的值。*/
??? char *i=NULL ;
??? char *j=NULL;
??? i= function1();//結吉確定
??? j= function2();//結果不確定
??? printf("/n%s/n",i);
??? printf("/n%s/n",j);
??? system("pause");
???
}
/*(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]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));//輸出:2,5

指針加1要根據指針類型加上一定的值,不同類型的指針+1之后增加的大小不同,指針只是一個內存地址,但指針指向地址的長度可能不同,如char *pc與int *pi,sizeof(pc)=sizeof(pi)=4,但為什么輸出時,cout<<*pc只從內存處取一個字符,而cout<<*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* p,即相當于int(*p)[5]).所以&a+1=&a的地址值+5*4字節,即變為數組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[]={1, 2, 578, 111,90} ;
double *pt= &t[3];//指向值為111
int *ptInt= reinterpret_cast< int * > (pt);
char *ptCh= reinterpret_cast< char * > (pt);
cout<< *( pt- 1)<< "\t"<< *(reinterpret_cast<double*>(ptInt-2))<<"\t"<<
*(reinterpret_cast<double*>(ptCh-8));//最后輸出結果全為578
---------------------
void Fun( int *p)與void Fun( int p[])是一樣的,即函數列表中的數組此時退化成了指針

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254152.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254152.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254152.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java中繼承thread類與實現Runnable接口的區別

Java中線程的創建有兩種方式&#xff1a; 1&#xff0e; 通過繼承Thread類&#xff0c;重寫Thread的run()方法&#xff0c;將線程運行的邏輯放在其中 2&#xff0e; 通過實現Runnable接口&#xff0c;實例化Thread類 在實際應用中&#xff0c;我們經常用到多線程&#xff0c;…

【VMware vSAN 6.6】6.2.啟用性能服務:vSAN硬件服務器解決方案

目錄 1. 簡介 1.1.適用于HCI的企業級存儲2. 體系結構 2.1.帶有本地存儲的服務器2.2.存儲控制器虛擬系統套裝的缺點2.3.vSAN在vSphere Hypervisor中自帶2.4.集群類型2.5.硬件部署選項3. 啟用vSAN 3.1.啟用vSAN3.2.輕松安裝3.3.主動測試4. 可用性 4.1.對象和組件安置4.2.重新構建…

Android eclipse導入項目后出現Unable to resolve target #39;android-17#39;解決方法

eclipse導入項目后出現Unable to resolve target android-17解決方法。在最后附帶還有一種編譯邏輯不成功情況解決方法。 一、問題情況 二、解決的方法 1、改動項目的目標版本號與當前Android sdk相相應的版本號 2、自己主動修復一下項目 三、這個問題不是上面的。是另外情況&a…

多個圓點,鼠標選取兩個,求兩個點的距離,用于計算像素尺寸(halcon實現)

read_image (Image, C:/Users/22967/Desktop/晶圓找位置/0.bmp) dev_close_window () dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) dev_display (Image)binary_threshold (Image, Region1, max_separability, dark, UsedThreshold) connection (Region1, C…

修改UBOOT和LINUX調試串口(TI達芬奇芯片--DM6467)

Posted on 2011-10-31 10:53 jamiedu 閱讀(889) 評論(0) 編輯 收藏 1.1 概述 TI針對DM6467提供的UBOOT和內核默認都是串口0作為調試串口輸出的&#xff0c;但現在我需要使用DM6467的UART0的modem功能&#xff0c;所以修改代碼&#xff0c;改變調試串口為串口2。 需要修改的主要…

Java List與數組之間的轉換

http://blog.csdn.net/kingzone_2008/article/details/8444678轉載于:https://www.cnblogs.com/longshiyVip/p/5985981.html

受歡迎的五個開源可視化工具——你的選擇是?

摘要&#xff1a;大數據時代&#xff0c;數據為王&#xff0c;還在對一堆數據而發愁嗎&#xff1f;試試可視化工具吧&#xff0c;相信本文提到的五款工具有一款能夠幫助到你。人工智能時代&#xff0c;數據和算法以及硬件資源是非常重要的&#xff0c;相關行業的大公司也越來越…

halcon車刀崩邊檢測

list_files (新建文件夾, files, Files) read_image (Image, Files[0]) dev_close_window () get_image_size (Image, Width, Height) dev_open_window (0, 0, Width/1.5, Height/1.5, black, WindowHandle) dev_set_draw (margin) dev_set_colored (12) for Index:0 to |Files…

FFMPEG解碼264文件步驟

本文以H264視頻流為例&#xff0c;講解解碼流數據的步驟。 為突出重點&#xff0c;本文只專注于討論解碼視頻流數據&#xff0c;不涉及其它&#xff08;如開發環境的配置等&#xff09;。如果您需要這方面的信息&#xff0c;請和我聯系。 準備變量 定義AVCodecContext。如果…

Storm概念學習系列之storm的特性

不多說&#xff0c;直接上干貨&#xff01; storm的特性 Storm 是一個開源的分布式實時計算系統&#xff0c;可以簡單、可靠地處理大量的數據流。 Storm支持水平擴展&#xff0c;具有高容錯性&#xff0c;保證每個消息都會得到處理&#xff0c;而且處理速度很快&#xff08;在一…

Confluence 6 配置服務器基礎地址示例

2019獨角獸企業重金招聘Python工程師標準>>> 如果 Confluence 的安裝是沒有安裝在非根目錄路徑&#xff08;這個是上下文路徑&#xff09;&#xff0c;然后服務器基礎 URL 地址應該包括上下文地址。例如&#xff0c;你的 Confluence 正在運行在下面的地址&#xff1…

BootstrapValidator驗證

bootstrap&#xff1a;能夠增加兼容性的強大框架. 因為項目需要數據驗證&#xff0c;看bootstrapValidator 還不錯&#xff0c;就上手一直&#xff0c;完美兼容&#xff0c;話不多說。 需要引用css&#xff1a; bootstrap.min.css bootstrapValidator.min.css js: jquery-1.10.…

基于ARM9的視頻采集傳輸系統

http://www.ic37.com/htm_tech/2007-11/77189_618093.htm

halcon找矩形頂點的一種方法

主程序&#xff1a; read_image (Image11, 11)*畫仿射矩形 dev_set_color (green) draw_rectangle2 (3600, Row, Column, Phi, Length1, Length2)*生成仿射矩形xld gen_rectangle2_contour_xld (Rectangle, Row, Column, Phi, Length1, Length2) *找頂點工具&#xff08;基于卡…

老男孩linux運維50期

一、自我介紹&#xff1a;我是來自老男孩Linux運維脫產50期的楊國峰&#xff0c;我以前是學軟件編碼的&#xff0c;但在大學里基本沒怎么學&#xff0c;每一門課都一知半解的&#xff0c;甚至有些連軟件都不會裝&#xff0c;在校期間&#xff0c;我對JAVA、網頁設計等都不感興趣…

博客收藏

http://www.dreamfairy.cn/blog/category/unity3d/轉載于:https://www.cnblogs.com/wantnon/p/5989843.html

移動開發平臺性能比較

jquerymobile是一個mobile平臺下的js框架,跟phonegap沒有一毛錢關系.phonegap實際上在國內占有率不高的,非常多人為了體驗喜歡做傳統的原生手機應用. 而Webapp如今的占有率越來越少,由于越來越多的人不喜歡用手機瀏覽器去體驗專門為移動平臺搭建的站點.我認為你的比較對象應該是…

H264關于RTP協議的實現

完整的C&#xff0f;S架構的基于RTP&#xff0f;RTCP的H&#xff0e;264視頻傳輸方案。此方案中&#xff0c;在服務器端和客戶端分別進行了功能模塊設計。服務器端&#xff1a;RTP封裝模塊主要是對H&#xff0e;264碼流進行打包封裝&#xff1b;RTCP分析模塊負責產牛和發送RTCP…

華為數通HCIE面試題目解密系列之RSTP邊緣端口

以下是華為數通面試考試的一道真題&#xff0c;原題如下&#xff1b; 請舉例說明 stp 的 edge port 的作用,用在什么場景&#xff0c;并且使用 edge port 會碰到什么問題&#xff0c;怎么解決和防止&#xff1f; 提到邊緣端口&#xff0c;我們是在NP課程的交換部分第一次接觸&a…

VS2013 Pro版本密鑰

Visual Studio Professional 2013 KEY&#xff08;密鑰&#xff09;&#xff1a; XDM3T-W3T3V-MGJWK-8BFVD-GVPKY 轉載于:https://www.cnblogs.com/Mysterious/p/5990358.html