創作內容

1 GP

【寫程式教學】新手篇3-c/c++指標

作者:♙♲⚙\~O_O~/⚙♲♙│2016-12-22 14:28:57│巴幣:2│人氣:370
指標(pointer)
指標用來存放記憶體位址[註1],每個變數如果有用到記憶體[註2],則變數會有個位址,我們可以用指標儲存這個位址

指標的宣告
在宣告變數的名稱前加上 * ,例如 int *a;

取址
想要取得某個變數的位址,可以在變數前加上 & ,例如 宣告 int b; 之後,可以 &b 取得 b 的位址

取內容
想要取得某位址的內容,可以在指標前加上 * ,例如
int b=123;
int *a=&b;
// 則
printf("%d",*a);
// 會印出 123

轉型[註3]
轉換型別,指標的轉換型別有幾條特別規則:
0, NULL 可以直接轉為任何指標
任何指標可以自動轉為 (void*)

指標轉型時其值不改變,而是"觀點"改變。前篇提到變數大小不同,那麼同樣的位址要看多少byte,或是怎麼看(例如int, float),就要看指標的型別了。

印出指標
printf 使用 %p
cout 可以直接印
例如:
int arr[16];
int b=0;
int *a=&b;
printf("%p  %p",a,arr);

與陣列的關係
陣列在宣告時,使用的記憶體空間是連續的。直接使用陣列變數,其值是陣列的起始位置([0])
可以藉由以下觀察:
// 別忘了 #include <stdio.h>
// 印出 陣列位址 和 陣列[0] 的位址
int arr[16];
printf("%p\n%p\n",arr,&arr[0]);

與常數字串的關係
直接使用常數字串,其實是個指標,型別是(const char*),這邊的 const 是指常數的意思,也就是沒辦法改
可以藉由以下觀察:
// 別忘了 #include <stdio.h>
const char *str="abc\n";
printf("----\n");
printf("%c%c%c%c----",*(str+0),*(str+1),*(str+2),*(str+3),*(str+4));
// 這些 %c 印出得字元分別是:'a' 'b' 'c' '\n' '\0'
// 然後前面提到陣列直接用是指標,除了sizeof外,其觀點是 &陣列[0]; ,所以也可以
printf("%c%c%c%c----",str[0],str[1],str[2],str[3],str[4]);
printf("----\n");


主要用途:
動態記憶體宣告
在c裡:(以下只介紹malloc)
藉由 malloc(sizeof(型別)*個數); 取得新的記憶體空間位址,要注意的是他的回傳型別是(void*),因此要自己在 malloc 前面加上型別
以及 free(指標); 註銷使用這個空間
要注意的是不能 free 2次(含以上),以及使用 free 過的位址會發生無法預期的結果
範例:
// 別忘了 #include <stdio.h>
int *a=(int*)malloc(sizeof(int)*10);
*(a+9)=10;
printf("%d",*(a+9));
// 然後前面提到陣列直接用是指標,除了sizeof外,其觀點是 &陣列[0]; ,所以也可以
printf("%d",a[9]);
free(a);

在c++裡:(以下只介紹1種new)
藉由
new 型別; 取得新的記憶體空間位址,不需額外轉型;對應使用 delete 指標; 將其註銷
new 型別[個數]; 取得連續的新的記憶體空間位址,不需額外轉型;對應使用 delete [] 指標; 將其註銷
範例:
// 別忘了 #include <iostream>
// 還有 using namespace std;
int *a=new int[10];
*(a+9)=10;
cout<<(*(a+9))<<endl;
cout<<  a[9]  <<endl;
delete [] a;

不管在c還是c++如果要不到新空間,回傳值都是NULL

在 function 內拿本尊(補充)
c/c++的 = 都是複製一份,傳進 function 時,若不是使用 c++的 reference type 則拿不到本尊
例如實作交換兩數的函式,比較下列的不同
// 別忘了 #include <stdio.h>
void exchange(int a.int b)
{
    printf("a,b: %d,%d\n",a,b);
    int tmp=a; a=b; b=tmp;
    printf("a,b: %d,%d\n",a,b);
}
void exchange_byptr(int *a.int *b)
{
    printf("a,b: %d,%d\n",*a,*b);
    int tmp=*a; *a=*b; *b=tmp;
    printf("a,b: %d,%d\n",*a,*b);
}
void exchange_byref(int &a,int &b)
{
    printf("a,b: %d,%d\n",a,b);
    int tmp=a; a=b; b=tmp;
    printf("a,b: %d,%d\n",a,b);
}
比較方法是在呼叫 function 前後將傳數變數的值印出來
例如:
int a=1,b=2;
printf("a,b: %d,%d\n",a,b);
exchange(a,b);
printf("a,b: %d,%d\n",a,b);
exchange_byptr(&a,&b);
printf("a,b: %d,%d\n",a,b);
exchange_byref(a,b);
printf("a,b: %d,%d\n",a,b);



1 邏輯位址,而非實體位址
2 有時compiler會優化,只用暫存器(register),或是宣告時告訴compiler建議用暫存器:register int a;
3 轉型時在要被轉型東西加上 (欲轉成的型別),例如 int a; (unsigned)a; 直接將 a 的記憶體內容以 unsigned 解讀



如果有不詳盡或是錯誤的地方,趕快通知我修改,如果是覺得篇章順序很怪的話 ... 本人不擅表達但盡力而為。
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=3422404
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:寫程式|教學|新手|C|C++

留言共 0 篇留言

我要留言提醒:您尚未登入,請先登入再留言

1喜歡★agold404 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:【寫程式教學】新手篇2-... 後一篇:【寫程式教學】新手篇4-...

追蹤私訊切換新版閱覽

作品資料夾

lemonade1120隨便逛逛的你
歡迎來小屋逛逛看看奇幻小說喔 :D看更多我要大聲說昨天16:18


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】