class 5 指標

26
CLASS 5 指指

Upload: rusti

Post on 04-Jan-2016

47 views

Category:

Documents


1 download

DESCRIPTION

CLASS 5 指標. int my_abs(int); int rect(int,int); int main(){ int x,y,r; printf(“ 請輸入長方型的長 :”); scanf(“%d”,&x); printf(“ 請輸入長方型的寬 :”); scanf(“%d”,&y); printf(“ 長方型的面積 :%d\n”,rect(my_abs(x), my_abs(y))); return 0; } int rect(int x,int y){ return x*y; } - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: CLASS 5  指標

CLASS 5 指標

Page 2: CLASS 5  指標

int my_abs(int); int rect(int,int); int main(){ int x,y,r; printf(“ 請輸入長方型的長 :”); scanf(“%d”,&x); printf(“ 請輸入長方型的寬 :”); scanf(“%d”,&y); printf(“ 長方型的面積 :%d\n”,rect(my_abs(x),

my_abs(y))); return 0; } int rect(int x,int y){ return x*y; } int my_abs(int num){ if(num<0)num*=-1; return num; }

Page 3: CLASS 5  指標

複習 srand(time(NULL)); int rand_num=(rand()%901)+100;//100~1000 printf(“ 亂數 :%d, 平方根 %lf\

n”,rand_num,sqrt(rand_num));

Page 4: CLASS 5  指標

想一想 下面這個函式作什麼事情?

應該是交換 num1 和 num2 ,但其實並沒有, why ? 因為上面的函式只是把變數的值傳進去,函式更改

的是變數的複製品,而不是真正變數在記憶體存放的值

Page 5: CLASS 5  指標

何謂指標? 一般正常的變數

儲存的是程式當中用來記錄或是做計算用的數值 指標變數

變數的內容儲存的是另一個變數的記憶體位址值

Page 6: CLASS 5  指標

兩個運算子 取址運算子( & )

取得一個變數的記憶體位址

提領運算子( * ) 間接讀取指標所指向的記憶體位址資料

Page 7: CLASS 5  指標

指標變數的宣告 語法

資料型態 * 指標變數名稱 ; 資料型態代表這個指標變數所存放的位址要以

什麼樣的資料型態(記憶體大小)來解讀 int *countPtr; 指定初始值的宣告

Int count; int *countPtr=&count;

Page 8: CLASS 5  指標

範例練習 實地操作變數、指標變數以及 * 、 & 運算子,

並觀察結果

0022FF74

0022FF70

countPtr

8

0022FF74

count

Page 9: CLASS 5  指標

為什麼要用指標? 當我們希望傳入的引數在函式中修改其值時,

我們必須利用指標變數來取得修改的權利 如果只有一個需要改變,也可利用 return

指標變數代表一個位址,假如我們有一塊很大的連續記憶體(如陣列)要傳入函式,使用指標變數是有效率的 因為在參數初始化時,只需複製一個位址,而不必

將整個連續記憶體的內容都複製一份 交換兩個複雜資料型態的變數時,只需交換指

向它們位址的指標即可,增加程式運算的速度

Page 10: CLASS 5  指標

範例練習 撰寫一個真正可以交換兩數的函式,並在主函

式呼叫它

Page 11: CLASS 5  指標

const 常數修飾子 int *ptr;

ptr 可變動, *ptr 也可變動 int *const ptr;

ptr 不可變動, *ptr 可變動 const int *ptr;

ptr 可變動, *ptr 不可變動 const int *const ptr;

ptr 不可變動, *ptr 也不可變動

Page 12: CLASS 5  指標

指標與陣列名稱 宣告陣列時,陣列的名稱本身就可以看作是一個

指標 常數指標 不能更改這個常數指標的值

存放的位址 陣列第一個元素在記憶體的位址

利用索引和這個記憶體位址,我們可以取得陣列中各元素的值

int array[5]; array 是一個位址 //printf(“%d”,array); //array[0] 放在 array+0*sizeof(int) 的位址 //array[2] 放在 array+2*sizeof(int) 的位址

Page 13: CLASS 5  指標

指標的運算 指標的加減運算,只有對陣列執行時才有意義

因為我們不能假設相同型態的兩個變數一定會連續地存放在記憶體中,除非它們是同一陣列內相鄰的兩個元素

int arr[6], *ptr=arr;printf(“%d”,*ptr); // 印出 100ptr++;printf(“%d”,*ptr); // 印出 200ptr+=2;printf(“%d”,*ptr); // 印出 400printf(“%d”,ptr-arr); // 印出 3

100 200 300 400 500 600

Page 14: CLASS 5  指標

陣列與指標的交換性 int arr[10],*ptr; ptr=arr; /* 這兩行 ptr=&arr[0]; 做的是一樣的事情 */

int arr[10],*ptr=arr; //ptr 為一指向 arr 的指標 arr[2] 、 *(arr+2) 、 ptr[2] 、 *(ptr+2) 是相同的東

西 注意

陣列與指標不同在於陣列名稱是常數指標 arr++;

不合法,因為 arr 是常數指標,不可更改指向位址 ptr++;

合法, ptr 是指標變數

Page 15: CLASS 5  指標

存取陣列裡的元素 使用 [ ] 陣列運算子

array[i] , i 值決定要取用從 array 位址起算要位移幾個元素長度,單位元素長度(記憶體大小)取決於陣列的資料型態

使用 * 提領運算子 array+i ,表示從 array 這個位址,位移 i 個單位

元素的位址,單位同樣取決於陣列的資料型態 給定位址後,配合提領運算子,取用第 i 個元素即

是用 *(array+i)

Page 16: CLASS 5  指標

指標與一維陣列 宣告一維陣列,程式執行時,系統會保留一塊

連續的記憶體 int array[8];

陣列 array 代表這一段連續記憶體的起始位址,亦即此陣列第

一個元素的記憶體位址( &array[0] )

array

25 35 18 29 100 121 5 9

Page 17: CLASS 5  指標

存取陣列裡的元素 2

(array+1)[2] 表示的是 *(array+1+2) 也就是array[3] 的位置

注意 因為 * 運算子的優先權大於 + ,所以 *array+i 表示的

是這個位址的元素値加上 i *(array+2) 是 18 *array+2 是 25+2=27 *(array+2) 是可接受數值的變數(可以放在指定運算

子 = 的左邊),但 *array+2 只是一個數值而已

25 35 18 29 100 121 5 9

array+1 array+1[2]

Page 18: CLASS 5  指標

練習 將長度為 5 的一維陣列傳入函式

( 用 rand() 產生 5~105 的值 ) 在函式內將陣列裡面的值 -5 在主程式印出新的值 void sub_five(int*); int main(){ int i,num[5]; srand(time(NULL)); // 亂數產生 5 個值 , 並印出 sub_five(num); // 印出陣列裡新的值 } void sub_five(int* num){ // 將陣列裡的值減 5 }

Page 19: CLASS 5  指標

指標與多維陣列 多維陣列的記憶體配置 每一個元素在記憶體裡順序,是以最低的維度排起,由小到大

int num[3][2];

num[0] num[1] num[2]

num 所指的單位元素是一個擁有 2 個整數的一維陣列

num[0][0] num[0][1] num[1][0] num[1][1] num[2][0] num[2][1]

Page 20: CLASS 5  指標

指標與多維陣列 2

在陣列宣告時,指定了較低的維度擁有 2 個元素,編譯器 (compiler) 看見 num[1] 才知道往後移動的一個單位是一個長度為 2 個整數的一維陣列

存取 num[1][0] 的寫法 num[1][0] (*(num+1))[0] *(*(num+1)+0) *(num[1]+0)

使用提領運算子後, *(num+1)仍然是一個指標

Page 21: CLASS 5  指標

以多維陣列為函式的參數 假設要傳給函式的是一個二維陣列,其宣告是 int

num[3][2]; 函式的參數列: void test(int num2[3][2]) { }

參數 num2 所指的是一個擁有兩個整數的一維陣列,總共有三個這樣的一維陣列

相同寫法 void test(int num2[ ][2]) { } void test(int (* num2)[2]) { }

不合法的寫法 void test(int *num2[2]) { } 宣告了一個陣列放了兩個指標變數

Page 22: CLASS 5  指標

指標的指定與轉換 int num[3][2], *num2; num2=num;

不合法的指定敘述 因為 num2 所指的元素是一個整數,而 num 所指的元素是

一個一維陣列 仍然可以透過強制型態轉換,把 num2成功的指向

num 所指的位址。 num2=(int *)num;

num2 跟 num分享同樣的位址

num2 num2[1] num2[2] num2[3] num2[4] num2[5]

num[0][0] num[0][1] num[1][0] num[1][1] num[2][0] num[2][1]

Page 23: CLASS 5  指標

補充 (malloc and free)

int main(){ int *pt; int size,i; printf(" 請輸入陣列的大小 : "); scanf("%d",&size); pt=(int*)malloc(sizeof(int)*size); for(i=0;i<size;i++) pt[i]=rand()%10+1; for(i=0;i<size;i++) printf("%d ",pt[i]); free(pt); system("pause"); }

Page 24: CLASS 5  指標

補充 (malloc and free)

( 指標的型態 )malloc (sizeof( 陣列的資料型態 )* 陣列大小 );

範例 float* pt=(float*)malloc(sizeof(float)*size); char* pt=(char*)malloc(sizeof(char)*size);

Page 25: CLASS 5  指標

作業六 參見 hw6.doc ( 到www.csie.ntu.edu.tw/~ r93041/C下載 )

Page 26: CLASS 5  指標

作業六 ( 也可以試著做這一個 )

讓使用者輸入陣列的大小 , 並產生 int 陣列 提示 :用 malloc

讓使用者輸入值到陣列裡 將陣列傳到一個自訂的函式裡 , 做排序 在主函式輸出排序結果