指針和數組

09年5月18日·張貼在的C / C + +

在第一本系列後,我們要講一些指針。 在第二,我們談論的引用。 今天,我們將集中在親密關係(牛耳!)在指針和數組(或數組)。

回顧陣列

一個數組,或陣列,或安排,這是一個抽象的數學用來表示一組數據的同質,即同一類型(整型,浮點,等等)。 這個抽象的組織表格式,行和列。 每個元素在數組的唯一坐標(行和列),這樣,一個給定元素e(一,十)是唯一的元素在“行我”的“J列。

語法申報陣列如下:

  / /一維數組或向量
 10 ] ; // 10 elementos, do 0 ao 9 ivet 廉政 [10] / / 10的內容,0到9
 23 ] ; // 23 elementos, do 0 ao 22 cvet 字符 [23] / / 23的元素,從0到22

 / /二維矩陣
 2 ] [ 3 ] ; // 2 linhas (0 a 1) e 3 colunas (0 a 2) 廉政 imat [2] [3] / / 2線(0到1)和3列(0〜2)
 10 ] [ 2 ] ; // 10 linhas (0 a 9) e 2 colunas (0 a 1)彈塑性材料 [10] [2] / / 10線(0到9)和2列(0到1) 

每個數組元素是獨立於其他人可以訪問如下語法:

  10 ] ; ivet 廉政 [10];
 3 ] [ 4 ] ; 廉政 imat [3] [4];

 / /更改第四個要素矢量的ivet。
 / /請記住開始運行從零元
 ] = 13 ; ivet [3] = 13;

 / /讀第二個元素的矢量ivet
 ivet [ 1 ] ; 廉政= ivet [1];

 / /更改元素的第一行,第二列imat
 ] [ 1 ] = 42 ; imat [0] [1] = 42;

 / /讀元素排在第三,第四欄imat
 imat [ 2 ] [ 3 ] ; 廉政= imat [2] [3]; 

在這個後,我們將不討論矩陣的背景,我們只研究之間的關係數組和指針在一個相當直觀。

尺寸陣列

由於數組是一個抽象的,它包含多個值相同類型的,有多大呢? 多少它佔據的空間在內存?

考慮下面的代碼:

  17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
  10 ] ; ivet 廉政 [10];
 13 ] ; cvet 字符 [13];
 20 ] ;  dvet [20];

 3 ] [ 4 ] ; CMAT 字符 [3] [4];
 5 ] [ 4 ] ; 廉政 imat [5] [4];

 "sizeof(int)     = " << sizeof ( int ) << endl ; 法院 “”“sizeof(廉政 )=”“”sizeof(廉政)“”endl;
 "sizeof(char)    = " << sizeof ( char ) << endl ; 法院 “”“sizeof(字符 )=”“”sizeof(字符)“”endl;
 "sizeof(double)  = " << sizeof ( double ) << endl ; 法院 “”“sizeof( )=”“”sizeof()“”endl;

 "sizeof(ivet)    = " << sizeof ( ivet ) << endl ; 法院“”“sizeof(ivet)=”“”sizeof(ivet)“”endl;
 "sizeof(cvet)    = " << sizeof ( cvet ) << endl ; 法院“”“sizeof(cvet)=”“”sizeof(cvet)“”endl;
 "sizeof(dvet)    = " << sizeof ( dvet ) << endl ; 法院“”“sizeof(dvet)=”“”sizeof(dvet)“”endl;
 "sizeof(cmat)    = " << sizeof ( cmat ) << endl ; 法院“”“sizeof(CMAT)=”“”sizeof(CMAT)“”endl;
 "sizeof(imat)    = " << sizeof ( imat ) << endl ; 法院 “”“sizeof(研究院)=”“”sizeof( 研究院)“”endl; 

結果是比較合理的。 佔用的空間由數組等於人數乘以元素的大小類型元素(行x列x sizeof(類型))。 但是,如果每個元素是獨立的,它假定每個佔據一個單獨的地方在內存中,否則人們將覆蓋其他元素。 那麼,每個元素都有自己的內存地址?

數組和內存地址

為方便起見,我們然後再分析可能的地址的字符數組,其大小只獲 1個字節:

  15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
  5 ; const廉政 = 5;
 max ] = { 'A' , 'B' , 'C' , 'D' , 'E' } ; cvet 字符 [最大 ] =('甲','乙'類,'C','D'類,'E'類);

 / /顯示的內容,價值和地址的數據。
 "Índice \t Valor \t Endereço do elemento \n " ) ; printf(“指數\ t\噸元素地址\ n”);
 int i = 0 ; i < max ; i ++ ) { 對於(整合酶 = 0;“最大的,我 + +)(
     "%d \t %c \t %p \n " , i, cvet [ i ] , & cvet [ i ] ) ; printf(“%d\噸%ç \噸%p \ N”的,我 cvet [一],&cvet [一]);
 

 / /打印的地址陣列
 "Endereço da matriz: %p \n " , & cvet ) ; printf(“地址的數組:%p \ N”型,  cvet);

 / /打印的地址再次陣列
 "Endereço da matriz: %p \n " , cvet ) ; printf(“地址的數組:%p \ N”的,cvet); 

的地址元素是連續的,即每個元素的存儲旁邊前者。 此外,還有兩個有趣的事實:

  1. 該地址的數組(&cvet),列於第25行,是一樣的第一個元素的數組;
  2. 變量 cvet非常可以理解為一個指針,如在第28行;

在C + +,一個共同的數組是一個連續的內存塊的名字可以解釋(投)作為指針指向它的第一個元素。 此外,它是有效的,使指針指向一個數組,指針目的地是同一類型,類型的數組元素。 在atrubuição數組的指針,使編譯器的隱式類型轉換。 指針的目的是要解釋為指針,內存佔用面積的數組。

其中一個後果不那麼明顯的是,在隱式轉換,丟失的資料,該地區是一個存儲陣列。 因此,丟失的信息大小的數組。 從觀點的指針,它指向的開始,一個任意內存塊,大小過於武斷。 查看數組和指針去就是去,從一個抽象的概念更嚴格和更高層的抽象為較少限制和較低的水平。

另一方面,嘗試分配的指針數組生成一個編譯錯誤類型不兼容。 數組是一個內存塊的n個數據(字節),作為一個指針只有一個輸入一個地址。 編譯器無法預先知道是否指針指向一個地區的1,2或200個字節。

  15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
  300 ; const廉政最大= 300;
 max ] ; cvet 字符 [最大];
 pc = 0 ; 字符 *電腦= 0;

 " \n Antes da atribuição \n " ) ; printf(“\ N先於轉讓\ N”的);
 "cvet = %p \n " , cvet ) ; printf(“cvet =%p \ N”的,cvet);
 "pc   = %p \n " , pc ) ; printf(“個人電腦=%p \ N”的, 個人電腦);
 "sizeof(cvet) = %lu \n " , sizeof ( cvet ) ) ; printf(“sizeof(cvet)=%祿\ N”的,sizeof(cvet));
 "sizeof(pc)   = %lu \n " , sizeof ( pc ) ) ; printf(“sizeof(支)=%祿\ N”的,sizeof( 件));

電腦= cvet;

 " \n Depois da atribuição \n " ) ; printf(“\ ñ後轉讓\ N”的);
 "cvet = %p \n " , cvet ) ; printf(“cvet =%p \ N”的,cvet);
 "pc   = %p \n " , pc ) ; printf(“個人電腦=%p \ N”的, 個人電腦);
 "sizeof(cvet) = %lu \n " , sizeof ( cvet ) ) ; printf(“sizeof(cvet)=%祿\ N”的,sizeof(cvet));
 "sizeof(pc)   = %lu \n " , sizeof ( pc ) ) ; printf(“sizeof(支)=%祿\ N”的,sizeof( 件)); 

請注意,轉讓前(行25) 個人電腦的指針 為 null,所以這是初始化。 由於規模表明,有300個字節數組和指針只有8(我的機器是AMD的64)。 轉讓後,都通過“點”同一地區的內存,但規模並沒有改變。 有一個隱含的轉換為char [300]為char *,指針在那場比賽PC可以不知道大小的內存區域它所點。 由於數組繼續cvet確切知道他是什麼,沒有任何生存危機。

指針運算 - 俗,又如何?

為什麼,如果我知道的數據數組排列並排,我可以用一個指針,將跳到下一個地址和訪問的下一個元素。 的名稱,這是算術指針。

  15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
  6 ; const廉政 = 6; 
 max ] = { 'B' , 'L' , 'A' , 'B' , 'O' , 'S' } ; cvet 字符 [最大] =('B' 類,『L','甲','乙','Ø','š');

 pc = cvet ; 字符 *電腦= cvet;

 int i = 0 ; i < max ; i ++ ) { 對於(整合酶 = 0;“最大的,我 + +)(
     "%c" , * ( pc + i ) ) ; printf(“%C”,*( 電腦 + i)條);
 
 " \n " ) ; printf(“\ N”的);

 int i = 0 ; i < max ; i ++ ) { 對於(整合酶 = 0;“最大的,我 + +)(
     "%c" , * pc ++ ) ; printf(“%C”,*電腦+ +);
 
 " \n " ) ; printf(“\ N”的);


 / /現在整個
 max ] = { 1 , 2 , 3 , 4 , 5 , 6 } ; ivet 廉政 [最大] =(1,2,3,4,5,6);
 pi = ivet ; 廉政 *= ivet;

 int i = 0 ; i < max ; i ++ ) { 對於(整合酶 = 0;“最大的,我 + +)(
     "%p = %d \n " , pi, * pi ++ ) ; printf(“%p =%d個\ N”型,皮,皮* + +);
 
 " \n " ) ; printf(“\ N”的);

 / /在兩個方面
 2 ] [ 3 ] = { { 'B' , 'L' , 'A' } , { 'B' , 'O' , 'S' } } ; CMAT 字符 [2] [3] =(('B' ,『L','甲'),('','Ø','š'));
 ppc ; 字符 * 每次點擊付費;

 char * ) cmat ;每次點擊付費=(字符 *)CMAT;

 int i = 0 ; i < 2 ; i ++ ) { 對於(整合酶 = 0;“2,我 + +)(
     int j = 0 ; j < 3 ; j ++ ) { (廉政 J = 0時,ĵ“3 ĵ + +)(
         "%c" , * ( ppc + 3 * i + j ) ) ; printf(“%C”,* 付費(PPC + 3 *+ j)條);
     
     " \n " ) ; printf(“\ N”的);
 
 " \n " ) ; printf(“\ N”的); 

在第18行指針電腦現在指向數組cvet,因此其第一個元素,字符'乙'。 在線 21電腦的內容,這是地址,它存儲在'B'類,即遞增然後去引用。 在第一週的i的值為零,因此間接引用的值'乙'。 在下面的,下面的地址已經被取消參照其他字符存儲在原數組。 這或多或少是什麼編譯器內部當您使用語法 cvet [一]。 在抽象的數組為您提供了更友好的方式處理毗連地區的內存*(電腦+一)。

但如果抽象數組比較簡單,使用該指針運算?

一個答案是26行。 她做同樣的事情該行21,但速度也較快。 在語法線 21,或類似的數組的語法,獲得的任何信息可以歸納為一個非常粗略的命令:

  1. 以基地址的數組;
  2. 添加到地址的值指標;
  3. 德參照新的地址;

已經與指針運算如下:

  1. 德參照此地址;

命令增量(或提出的關於地址)將不會計算,因為它是循環的一部分, 雖然+ +;快於1 =乙+丙;。 現在想像這個小增益66%應用於數據區為 1 MB。 將有超過 200萬的命令少!

該技術使用一個指針來處理任意區域的內存通常用於在低一級的方案(接近機),操縱緩衝器和字符串,以及其他骯髒的詭計。 在大便計算機,操作掃描大面積的內存,往往表現的指針。 在這個層面上, 達爾文至高無上,只有準備生存。 從這裡開始的語言賦予的權力,只有純心可以理解。

一個重要的注意的是,行與行之間 31和38的經驗反复整數。 請注意,由於整數是4個字節的增量自動作出4項 4個字節,而不是1比1,即增量自動計算 sizeof(類型)。 提高指針指到下一個地區訪問的內存類似的實際數據,而不僅僅是下一個地址。 隨著規模的一個 char是一個字節,當 incremetamos字符的指針,移動只有1個字節。 如果推進的指針將增加一倍,我們會提出8個字節,依此類推。

另一種看法是,二維數組可以是“線性”所示線 40至52。 這是有用的,適用時,更好地利用高速緩存的處理器,例如。

無效*的Pansexual指針

剛才我說,這是唯一可行的分配數組的指針,是為同一類型,數組數據。 餘公然撒謊! 原因是有人誰放棄了這個問題前,後,它更安全相信它能夠 :)

有兩個例外的規則。 第一種情況是有一個明確的轉換指針的類型和目標“認為”,也就是指向合適的。 一個例子是在第44行以前的代碼。

二是案件指針無效。 阿指針無效是一個指針,不作任何要求的類型的數據是該地區的內存它所點。 他是一個指針普拉一般內存區域,東西非常低的水平。

要使用的任何資料所指向的指針無效之前,去引用它,你必須作出明確轉換為有效的類型,它是一個 int *是去參照一個 int和char *是去參照字符,你猜它是什麼去引用一個 void *?

  15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
  6 ; const廉政 = 6; 
 max ] = { 'B' , 'L' , 'A' , 'B' , 'O' , 'S' } ; cvet 字符 [最大] =('B' 類,『L','甲','乙','Ø','š');

 pv = cvet ; 無效 *光伏= cvet;

 / /編譯錯誤。
 / / *光伏
 / /多少sizeof(無效)?

 int i = 0 ; i < max ; i ++ ) { 對於(整合酶 = 0;“最大的,我 + +)(
     "%c" , * ( ( ( char * ) pv ) + i ) ) ; printf(“%C” ,*(((字符 *)光伏)+ 1));
 
 " \n " ) ; printf(“\ N”的); 

無效指針時,使用一個需要指向一般地區的內存,而不必控制/知識類型的數據,這一地區包含,或功能,不能假設有關類型的參數,如空氣污染指數lib pthreads的 (鏈接任意)。

關閉

我們越是深入探討的議題上的指針,機器旁邊我們。 大部分的權力 C和C + +來自那裡,許多問題仍然不少。 越來越多的複雜性和風險太大。 對於許多潛藏的樂趣!

鏈接

評論

一對“指針和數組

  1. 萊安梅洛於2009年5月21日21時50分

    井說教。 我喜歡“pansexual指針。 :)

留下回复




本站由可濕性粉劑Hashcash