文章程式碼顯示

2018年2月9日 星期五

《筆記》C語言 - 07_2:指標與陣列、指標算術運算

指標與陣列

#include "stdio.h"

int main(void) {

 int array[5] = { 0, 1, 2, 3, 4 }; //宣告一個陣列
 int* arrayPtr = NULL; //宣告一個名為 arrayPtr 的指標變數,指向 int型別。並預設指向 NULL 地址(0)

  printf("Address array = %p \n", array);
  printf("Address &array = %p \n", &array);
  printf("Address &array[0] = %p \n", &array[0]);
  printf("Address &array[1] = %p \n", &array[1]);
  printf("Address &array[2] = %p \n", &array[2]);
  printf("Address &array[3] = %p \n", &array[3]);
  printf("Address &array[4] = %p \n\n", &array[4]);

  for( int i = 0; i < 5; i++){
   printf("array[%d] = %d \n", i, array[i] );
  }

  printf("\n");

  for( int i = 0; i < 5; i++){
   printf("*(array + %d) = %d \n", i, *(array + i ));
  }

  return 0;
}



由前面的章節我們知道當我們宣告一個指標變數,其存放的數值必然是一個地址,且可以由 *(米字號) 前面的型別來觀察出指向的數值應該要是什麼型別

接著我們來證明一下

「陣列是一群具有相同名稱以及相同型別(type)的變數集合,在記憶體中擁有連續存放空間的集合」

首先我宣告一個具有 5 個元素的陣列 array ,且存放的數值為 { 0,1,2,3,4 }

接著我們用 print 函數分別列印出下列三者的位址(Address)

1. array
2. &array
3. &array[0]

我們可以發現以上三者位址都是 0x0028FF20

首先第一個我們的參數是 陣列名稱 ;第二個我們使用 取址運算元來取陣列名稱的位址;第三個我們用 取址運算元取陣列第一個元素的位址

也就是說 三者對應到的位址都是等價的都是 陣列第一個元素的位址

接著我們看看其它元素的位址,我們可以發現相鄰元素之間的地址差値為 4
這是因為我們宣告的是一個 int 型別 的陣列

int 型別陣列一個元素所佔據的大小就是 4 個 bytes

第 17 行為我們之前學過的,直接依中括弧內輸入 index ,就能取用到對應的元素。

第 23 行則是使用指標不斷加 1 來進行間接取値,也就是說 指標是可以進行運算的

這邊大家或許會困惑 0x0028FF20 +1 不是 0x0028FF21 嗎? 

困惑 : 
那這樣子 0x0028FF20 +1 不就變成 *(0x0028FF21) ? 怎麼會對應到 array[1] 呢? 應該要是 *(0x0028FF24) 才會抓到 array[1] 的値啊 ?

解答 : 
事實上 0x0028FF20 +1 還真的會自動變為 0x0028FF24
其原因請看下方的指標算術運算

: 第 23 行的陣列元素取値方法比第 17 行更為常用

指標的算術運算

#include "stdio.h"

int main(void) {

 int array[5] = { 0, 1, 2, 3, 4 }; //宣告一個陣列
 int * arrayPtr = NULL; //宣告一個名為 arrayPtr 的指標變數,指向 int型別。預設指向 NULL 地址(0)

  arrayPtr = array; //arrayPtr 指向 array(陣列名稱,又為指標常數,陣列第一個元素的位址)
  printf("arrayPtr = %x , *arrayPtr = %d \n\n", arrayPtr, *arrayPtr );
  arrayPtr++; //指標可執行遞增、遞減運算子(當某個指標要加或減上一個整數時,會加上或減去這個整數乘以指標所指向的物件的大小)
  printf("arrayPtr++ = %x , *arrayPtr++ = %d \n\n", arrayPtr, *arrayPtr );

  int Ptr_diff = arrayPtr - array; //指標變數之間可以進行相加減
  printf("arrayPtr - array = %d\n\n", Ptr_diff);
  // 註:指標的算術運算只對陣列有意義,因為相同陣列的兩個相鄰元素會連續存放於記憶體中
}



指標可以進行遞增以及遞減的算術運算,但這裡有一個很特別的點在於若我們對指標變數 +1 ,其會自動參考該位址存放的變數的型態所佔據的 byte 長度來進行遞增

例如在上述程式碼中我們將陣列名稱(等價為陣列第一個元素的位址)存放在指標變數 arrayPtr 之中,並顯示出來。

可以看到陣列的位址是 0x0028FF24

接著我們執行 arrayPtr++ ,等同於 arrayPtr = arrayPtr + 1 。也就是該指標變數自累加

列印出新的 arrayPtr 所存放的値(會是一個位址),發現是 0x0028FF28

原因在於 arrayPtr 指向 int型別(4bytes)。

將兩個指標(位址)進行相減,發現得出來的値是 1

這是很特別的部分,因為

它計算出來的結果不只是兩個地址之間的差值還考慮了變數型別為多少長度

我們必須好好的區別指標的算術運算與普通變數之間的算術運算

也就是說我們要知道

當我們在對指標變數進行運算時,僅記! 該指標變數所指向的變數型態長度是會自動被進行參考的

指標本身也可以使用邏輯判斷,但用處不大。多半是用來比較同一陣列中兩個不同元素的位址,用來知道兩個元素之間的相對位子。


↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引