C語言自學攻略-指標

更新於 發佈於 閱讀時間約 8 分鐘

認識指標

指標,用來儲存變數的記憶體位址,宣告方式如下:

資料型別 *變數名稱 or 資料型別* 變數名稱

假設今天有一個整數變數x,內容為38,那我們如何利用指標接收變數x的記憶體位址呢? 方法如下:

int *p = &x;

現在指標(64位元電腦下通常為8bytes)和變數在記憶體中的樣子如下圖所示:

raw-image
  • 我們假設指標記憶體位址為0x7ffd8d3f7f46 - 0x7ffd8d3f7f52

接著我們試著用指標輸出內容: 以下示範:

#include<stdio.h>

int main()
{
int *p, x=38;
p = &x;
printf("%p",p); //輸出變數x的記憶體位址,以16進制表示
return 0;
}

接著我們想要利用指標輸出變數x的內容,如何實現? 方法如下:

#include<stdio.h>

int main()
{
int *p, x=38;
p = &x;
printf("%d",*p); //輸出變數x的內容
return 0;
}

上面程式碼中,我們藉由在p前面添加*(我們稱這樣為解參考)。

好,今天我又想宣告一個指標儲存p的記憶體位址,如何實現? 方法如下:

#include<stdio.h>

int main()
{
int *p, x=38;
p = &x;

int **ptr = &p;
printf("%p\n",p); //輸出變數x的記憶體位址,以16進制表示
printf("%p\n",ptr); //輸出p的記憶體位址,以16進制表示
printf("%p\n",*ptr); //輸出變數x的記憶體位址,以16進制表示
printf("%d",**ptr); //輸出變數x的內容
return 0;
}

陣列名稱可以當作指標?!

#include <stdio.h>

int main() {
int test[5]={60,70,80,90,100};
printf("%p\n",&test[0]);
printf("%p",test);
return 0;
}
/* 輸出
0x7ffffdcab4f0
0x7ffffdcab4f0
*/
  • 從上面程式碼我們發現,一維陣列名稱test&a[0]的輸出相同,表示了test其實也可以做為一個指標(隱式轉換),指向a[0]的記憶體位址。

接著我們再做一些變化並測試:

#include <stdio.h>

int main() {
int test[5]={60,70,80,90,100};
printf("%p\n",&test[0]+1);
printf("%p",test+1);
return 0;
}
/* 輸出
0x7ffffdcab4f4
0x7ffffdcab4f4
*/
  • 從上面程式碼,我們發現,當test+1(等同&test[0]+1)時,輸出的記憶體位址增加了4,其實不難理解,意思就是他指向了一維陣列下一個儲存空間的記憶體位址,即a[1]的記憶體位址。我們一樣可以透過解參考輸出陣列內容。如下示範:
#include <stdio.h>

int main() {
int test[5]={60,70,80,90,100};
printf("%d\n",*test);
printf("%d",*(test+1));
//printf("%d",*test+1); 這樣寫會變為60+1等於61
return 0;
}
/* 輸出
60
70
*/

好,現在如果我想要再宣告一個指標指向這個陣列,只要把名字test丟給指標就行,如下示範:

#include <stdio.h>

int main() {
int a[5]={60,70,80,90,100};
int *p = a;
printf("%p\n",a);
printf("%d\n",*a);
printf("%p\n",a+1);
printf("%d\n",*(a+1));

printf("%p\n",p);
printf("%d\n",*p);
printf("%p\n",p+1);
printf("%d\n",*(p+1));

printf("%p\n",&p[0]);
printf("%d\n",p[0]);
printf("%p\n",&p[1]);
printf("%d\n",p[1]);

return 0;
}
/* 輸出
0x7fffb32eb0e0
60
0x7fffb32eb0e4
70
0x7fffb32eb0e0
60
0x7fffb32eb0e4
70
0x7fffb32eb0e0
60
0x7fffb32eb0e4
70
*/
  • 上面程式碼值得一提的是,p也可以使用索引的方式存取陣列,使用上就像是a

接著,我還有一些觀念想講:

觀念釐清

  1. 在 C 語言中,陣列名會被隱式地轉換為指向其第一個元素的指標。然而,當使用取位址運算符(&)時,情況有所不同。
  • a 在表達式中,a 會被視為指向陣列第一個元素的指標,型別為 int*(假設 aint 型別的陣列)。
  • &a 這裡,&a 取得的是整個陣列 a 的位址,其型別為 int (*)[N],其中 N 是陣列的大小。

  1. 型別區別
  • int* 指向 int 型別的指標。
  • int (*)[N] 指向大小為 Nint 陣列的指標。

  1. 指標算術中的位址計算

指標算術中的位址計算取決於指標的型別和指標運算。當對指標進行加法(如 ptr + 1)時,實際的位址增加量為 1 * sizeof(指標所指向的型別)

  • 對於 int* ptr + 1 將位址增加 1 * sizeof(int)
  • 對於 int (*)[N]ptr + 1 將位址增加 1 * sizeof(int[N]),也就是 N * sizeof(int)

假設我們有一個陣列:

int a[4] = {1, 2, 3, 4};
  • &a 的型別: int (*)[4],即指向包含 4 個整數的陣列的指標。
  • &a + 1 由於 &a 的型別是 int (*)[4],因此加1時,實際增加的位址為 1 * sizeof(int[4]),也就是 1 * (4 * sizeof(int))

示例 1:使用 &a(指向整個陣列的指標)

int a[4] = {1, 2, 3, 4};
int (*p)[4] = &a; // p 的型別是 int (*)[4]

printf("%p\n", p); // 輸出陣列 a[0] 的位址
printf("%p\n", p + 1); // 輸出位址增加 4 * sizeof(int) 後的位址
  • p + 1 將位址增加 4 * sizeof(int)

示例 2:使用 a(指向第一個元素的指標)

c
int a[4] = {1, 2, 3, 4};
int *p = a; // p 的型別是 int*

printf("%p\n", p); // 輸出 a[0] 的位址
printf("%p\n", p + 1); // 輸出位址增加 sizeof(int) 後的位址
  • p + 1 將位址增加 sizeof(int)

留言
avatar-img
留言分享你的想法!
avatar-img
電資鼠 - 您的學習好夥伴
9會員
215內容數
在當今數位時代,電資領域人才需求爆發式成長,不論是前端網頁設計、嵌入式開發、人工智慧、物聯網還是軟硬體整合,這些技術都在改變世界。而掌握 C/C++、Python、數位邏輯、電路學與嵌入式開發等大學電資領域的課程,正是進入這個高薪、高需求產業的關鍵!
2025/03/07
本章節將探討左下三角稀疏矩陣。
Thumbnail
2025/03/07
本章節將探討左下三角稀疏矩陣。
Thumbnail
2025/03/07
相信讀者現在對於鏈結串列有了更多的認識,所以我再進一步,示範更多關於鏈結串列的操作,這部分示範會將程式模組化。將鏈結串列的操作寫進一個標頭檔,並在主程式中引入。
Thumbnail
2025/03/07
相信讀者現在對於鏈結串列有了更多的認識,所以我再進一步,示範更多關於鏈結串列的操作,這部分示範會將程式模組化。將鏈結串列的操作寫進一個標頭檔,並在主程式中引入。
Thumbnail
2025/03/07
本章節示範透過「陣列索引」和「指標運算」兩種方式來存取同一個二維陣列 a,並印出相同的數值以及對應的位址,以說明它們其實指向的是同一塊連續的記憶體空間。本文將依序解釋各段程式碼,並示範可能的執行結果與背後原理。
Thumbnail
2025/03/07
本章節示範透過「陣列索引」和「指標運算」兩種方式來存取同一個二維陣列 a,並印出相同的數值以及對應的位址,以說明它們其實指向的是同一塊連續的記憶體空間。本文將依序解釋各段程式碼,並示範可能的執行結果與背後原理。
Thumbnail
看更多
你可能也想看
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
了解這些運算子及其優先等級有助於更好地理解和編寫 JavaScript 代碼
Thumbnail
了解這些運算子及其優先等級有助於更好地理解和編寫 JavaScript 代碼
Thumbnail
在本章節中,我們將學習JavaScript的基本語法,包括如何註解代碼和如何聲明變數。瞭解這些基礎知識對於進一步學習和使用JavaScript來編寫代碼是非常重要的。
Thumbnail
在本章節中,我們將學習JavaScript的基本語法,包括如何註解代碼和如何聲明變數。瞭解這些基礎知識對於進一步學習和使用JavaScript來編寫代碼是非常重要的。
Thumbnail
C 語言的函式庫定義了許多好用的函式,在寫 C++ 的時候可以拿來用。這是因為 C++ 當初在設計的時候,就有刻意把 C 涵蓋進來。 基本用法 首先要導入 C 語言的標準函式庫: #include <cstdlib> 以 c 作為開頭表示它是 C 語言的函式庫,只是被我們拿來 C++ 的程式
Thumbnail
C 語言的函式庫定義了許多好用的函式,在寫 C++ 的時候可以拿來用。這是因為 C++ 當初在設計的時候,就有刻意把 C 涵蓋進來。 基本用法 首先要導入 C 語言的標準函式庫: #include <cstdlib> 以 c 作為開頭表示它是 C 語言的函式庫,只是被我們拿來 C++ 的程式
Thumbnail
在為「質數」此純數學範疇搜索相關的教學資源時,我發現到一個很好用的教具,那就是「Anchor Chart(錨點圖)」,類似於「海報展示」,對於純數學抽象概念的引導、闡明非常有幫助。
Thumbnail
在為「質數」此純數學範疇搜索相關的教學資源時,我發現到一個很好用的教具,那就是「Anchor Chart(錨點圖)」,類似於「海報展示」,對於純數學抽象概念的引導、闡明非常有幫助。
Thumbnail
高中數學主題練習—C計算(一)
Thumbnail
高中數學主題練習—C計算(一)
Thumbnail
解決電腦上遇到的問題、證明正確性、探討效率 並且很著重溝通,說服別人你做的事是正確且有效率的。 內容: 計算模型、資料結構介紹、演算法介紹、時間複雜度介紹。
Thumbnail
解決電腦上遇到的問題、證明正確性、探討效率 並且很著重溝通,說服別人你做的事是正確且有效率的。 內容: 計算模型、資料結構介紹、演算法介紹、時間複雜度介紹。
Thumbnail
編輯的基本功,是對文字的敏感度。
Thumbnail
編輯的基本功,是對文字的敏感度。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News