【C】數組和指針的關系

C 語言C++ 中,數組和指針 有非常密切的關系。它們在某些情況下表現類似,但也有重要的區別。理解數組和指針的關系對于掌握低級內存操作和優化程序性能至關重要。


1. 數組和指針的基本關系

  • 數組是一個 連續存儲的元素集合,在內存中占據一段連續的地址空間。
  • 數組的名稱(如 arr)在很多情況下會退化為指向數組第一個元素的指針

1.1 數組名是一個指針的表現

假設有一個數組:

int arr[5] = {1, 2, 3, 4, 5};
  1. 數組名的含義:

    • arr 是一個常量指針,指向數組的第一個元素(&arr[0])。
    • arr 的類型是 int*
  2. 數組元素的訪問:

    • arr[i] 等價于 *(arr + i)
    • 例如:
      printf("%d\n", arr[2]);  // 輸出 3
      printf("%d\n", *(arr + 2));  // 等價于上面
      
  3. 地址的訪問:

    • arr 是數組第一個元素的地址:&arr[0]
    • &arr 是整個數組的地址,類型是 int (*)[5],和 &arr[0] 不同。
    • 示例:
      printf("%p\n", arr);     // 輸出數組第一個元素的地址
      printf("%p\n", &arr[0]); // 等價于 arr
      printf("%p\n", &arr);    // 輸出整個數組的地址(類型是 int (*)[5])
      

2. 數組和指針的區別

盡管數組名和指針表現很相似,但它們并不完全相同:

2.1 內存分配

  • 數組
    • 數組是一個固定大小的內存塊,在定義時分配內存。
    • 例如:
      int arr[5]; // 為數組分配了連續的 5 個 int 空間
      
  • 指針
    • 指針是一個變量,它存儲的是地址,可以動態指向不同的位置。
    • 例如:
      int* ptr;
      ptr = malloc(5 * sizeof(int)); // 動態分配 5 個 int 空間
      

2.2 數組名是常量,指針是變量

  • 數組名是常量指針,不能重新賦值。

    • 示例:
      int arr[5];
      arr = arr + 1; // 錯誤,數組名不能作為左值
      
  • 指針是變量,可以隨時指向其他地址。

    • 示例:
      int* ptr;
      int x = 10, y = 20;
      ptr = &x; // 指向 x
      ptr = &y; // 可以改變指向,指向 y
      

2.3 使用 sizeof 的區別

  • 對數組和指針使用 sizeof 的結果不同:

    • 數組 返回整個數組的大小。
    • 指針 返回指針變量本身的大小(通常是 4 或 8 字節,取決于系統架構)。

    示例:

    int arr[5] = {1, 2, 3, 4, 5};
    int* ptr = arr;printf("%zu\n", sizeof(arr)); // 輸出 20(5 個 int 的大小)
    printf("%zu\n", sizeof(ptr)); // 輸出 8(指針本身的大小,假設是 64 位系統)
    

2.4 數組和指針的類型

  • 數組名和指針的類型不同:
    • arr 的類型是 int[5],退化后是 int*
    • ptr 的類型是 int*,可以自由賦值。

3. 數組和指針在函數中的關系

3.1 數組作為函數參數時會退化為指針

當數組作為函數參數傳遞時,數組會退化為指針傳遞,函數實際上接收到的是指向數組第一個元素的指針。

示例:

void printArray(int arr[], int size)
{for (int i = 0; i < size; i++){printf("%d ", arr[i]); // 等價于 *(arr + i)}
}int main()
{int arr[5] = {1, 2, 3, 4, 5};printArray(arr, 5); // 傳遞的是 int* 指針return 0;
}
實際的函數簽名

上述函數 void printArray(int arr[], int size) 實際等價于:

void printArray(int* arr, int size);

3.2 多維數組的函數參數

多維數組的第一級會退化為指針,但其余維度需要明確指定大小。

示例:

void print2DArray(int arr[][3], int rows)
{for (int i = 0; i < rows; i++){for (int j = 0; j < 3; j++){printf("%d ", arr[i][j]); // 訪問二維數組元素}printf("\n");}
}int main()
{int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};print2DArray(arr, 2); // 傳遞的是 int (*)[3] 指針return 0;
}
注意
  • 函數參數中必須指定第二維(3),因為編譯器需要知道每行的長度。

4. 結合使用數組和指針的技巧

4.1 動態分配多維數組

可以使用指針動態分配多維數組,而不是直接定義多維數組。

示例:

int** create2DArray(int rows, int cols)
{int** arr = malloc(rows * sizeof(int*)); // 分配行指針for (int i = 0; i < rows; i++){arr[i] = malloc(cols * sizeof(int)); // 分配每行的數據}return arr;
}

4.2 遍歷數組的指針操作

可以使用指針運算遍歷數組,而不使用下標。

示例:

int arr[5] = {1, 2, 3, 4, 5};
int* ptr = arr; // 指向數組第一個元素for (int i = 0; i < 5; i++)
{printf("%d ", *(ptr + i)); // 使用指針訪問元素
}

5. 小結

數組和指針的相似點:

  1. 數組名可以退化為指向第一個元素的指針。
  2. 數組元素可以通過下標或指針運算訪問。

數組和指針的區別:

  1. 數組名是常量指針,指針變量可以自由賦值。
  2. sizeof 操作在數組和指針上有不同的行為。
  3. 數組有固定大小,指針可以動態指向不同的位置。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/66090.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/66090.shtml
英文地址,請注明出處:http://en.pswp.cn/web/66090.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Maven 配置本地倉庫

步驟 1&#xff1a;修改 Maven 的 settings.xml 文件 找到你的 Maven 配置文件 settings.xml。 Windows: C:\Users\<你的用戶名>\.m2\settings.xmlLinux/macOS: ~/.m2/settings.xml 打開 settings.xml 文件&#xff0c;找到 <localRepository> 標簽。如果沒有該標…

Docker save load 鏡像 tag 為 <none>

一、場景分析 我從 docker hub 上拉了這么一個鏡像。 docker pull tomcat:8.5-jre8-alpine 我用 docker save 命令想把它導出成 tar 文件以便拷貝到內網機器上使用。 docker save -o tomcat-8.5-jre8-alpine.tar.gz 鏡像ID 當我把這個鏡像傳到別的機器&#xff0c;并用 dock…

O2O同城系統架構與功能分析

2015工作至今&#xff0c;10年資深全棧工程師&#xff0c;CTO&#xff0c;擅長帶團隊、攻克各種技術難題、研發各類軟件產品&#xff0c;我的代碼態度&#xff1a;代碼虐我千百遍&#xff0c;我待代碼如初戀&#xff0c;我的工作態度&#xff1a;極致&#xff0c;責任&#xff…

《盤古大模型——鴻蒙NEXT的智慧引擎》

在當今科技飛速發展的時代&#xff0c;華為HarmonyOS NEXT的發布無疑是操作系統領域的一顆重磅炸彈&#xff0c;其將人工智能與操作系統深度融合&#xff0c;開啟了智能新時代。而盤古大模型在其中發揮著至關重要的核心作用。 賦予小藝智能助手超強能力 在鴻蒙NEXT中&#xf…

走出實驗室的人形機器人,將復刻ChatGPT之路?

1月7日&#xff0c;在2025年CES電子展現場&#xff0c;黃仁勛不僅展示了他全新的皮衣和采用Blackwell架構的RTX 50系列顯卡&#xff0c;更進一步展現了他對于機器人技術領域&#xff0c;特別是人形機器人和通用機器人技術的篤信。黃仁勛認為機器人即將迎來ChatGPT般的突破&…

EF Core執行原生SQL語句

目錄 EFCore執行非查詢原生SQL語句 為什么要寫原生SQL語句 執行非查詢SQL語句 有SQL注入漏洞 ExecuteSqlInterpolatedAsync 其他方法 執行實體相關查詢原生SQL語句 FromSqlInterpolated 局限性 執行任意原生SQL查詢語句 什么時候用ADO.NET 執行任意SQL Dapper 總…

Java中網絡編程的學習

目錄 網絡編程概述 網絡模型 網絡通信三要素: IP 端口號 通信協議 IP地址&#xff08;Internet Protocol Address&#xff09; 端口號 網絡通信協議 TCP 三次握手 四次揮手 UDP TCP編程 客戶端Socket的工作過程包含以下四個基本的步驟&#xff1a; 服務器程序…

HarmonyOS NEXT開發進階(七):頁面跳轉

文章目錄 一、前言二、頁面跳轉三、頁面返回四、頁面返回前增加確認對話框4.1 系統的默認詢問框4.2 自定義詢問框 五、拓展閱讀 一、前言 APP開發過程中&#xff0c;多頁面跳轉場景十分常見&#xff0c;例如&#xff0c;登錄 -> 首頁 -> 個人中心。在鴻蒙開發中&#xf…

【Python】第一彈---解鎖編程新世界:深入理解計算機基礎與Python入門指南

?個人主頁&#xff1a; 熬夜學編程的小林 &#x1f497;系列專欄&#xff1a; 【C語言詳解】 【數據結構詳解】【C詳解】【Linux系統編程】【MySQL】【Python】 目錄 1、計算機基礎概念 1.1、什么是計算機 1.2、什么是編程 1.3、編程語言有哪些 2、Python 背景知識 2.…

LeetCode:131. 分割回文串

跟著carl學算法&#xff0c;本系列博客僅做個人記錄&#xff0c;建議大家都去看carl本人的博客&#xff0c;寫的真的很好的&#xff01; 代碼隨想錄 LeetCode:131. 分割回文串 給你一個字符串 s&#xff0c;請你將 s 分割成一些子串&#xff0c;使每個子串都是回文串。返回 s 所…

優化神馬關鍵詞排名原理(優化神馬搜索引擎關鍵詞排名規則)

優化神馬&#xff08;即百度&#xff09;關鍵詞排名的原理主要基于搜索引擎的算法和用戶體驗的考量。以下是一些關鍵的優化原理&#xff1a; 一、搜索引擎算法 網頁重要性評估&#xff1a; 搜索引擎通過復雜的算法評估網頁的重要性和權威性&#xff0c;如基于PageRank的評估方…

學習threejs,使用FlyControls相機控制器

&#x1f468;??? 主頁&#xff1a; gis分享者 &#x1f468;??? 感謝各位大佬 點贊&#x1f44d; 收藏? 留言&#x1f4dd; 加關注?! &#x1f468;??? 收錄于專欄&#xff1a;threejs gis工程師 文章目錄 一、&#x1f340;前言1.1 ??THREE.FlyControls 相機控制…

Vue 3前端與Python(Django)后端接口簡單示例

項目 后端&#xff08;Django&#xff09;前端&#xff08;Vue 3&#xff09; 后端&#xff08;Django&#xff09; 創建Django項目和應用&#xff1a; 確保你已經安裝了Django。如果沒有安裝&#xff0c;可以使用以下命令安裝&#xff1a; pip install django創建一個新的Dja…

MCP Server開發的入門教程(python和pip)

使用python技術棧開發的簡單mcp server 需要安裝 MCP server的需要使用python-sdk,python需要 3.10,安裝如下 pip install mcpPS: MCP官方使用的是uv包管理工具,我平時使用pip比較多,所以文中以pip為主。因為mcp的一些依賴包版本并不是最新的,所以最好弄一個干凈的環境…

Spark vs Flink分布式數據處理框架的全面對比與應用場景解析

1. 引言 1.1 什么是分布式數據處理框架 隨著數據量的快速增長&#xff0c;傳統的單機處理方式已經無法滿足現代數據處理需求。分布式數據處理框架應運而生&#xff0c;它通過將數據分片分布到多臺服務器上并行處理&#xff0c;提高了任務的處理速度和效率。 分布式數據處理框…

隱私計算,構建安全的未來數據空間

大數據產業創新服務媒體 ——聚焦數據 改變商業 在醫療領域&#xff0c;不同醫院之間需要共享患者數據&#xff0c;以提供更全面準確的診斷和治療方案。 傳統的數據處理方式通常是數據經過轉換隱藏重要數據后再進行分析&#xff0c;雖然可以保護數據隱私&#xff0c;但在數據源…

PID控制器 (Proportional-Integral-Derivative Controller) 算法詳解及案例分析

PID控制器 (Proportional-Integral-Derivative Controller) 算法詳解及案例分析 目錄 PID控制器 (Proportional-Integral-Derivative Controller) 算法詳解及案例分析1. 引言2. PID控制器的基本概念2.1 PID控制器的定義2.2 PID控制器的核心思想2.3 PID控制器的應用領域3. PID控…

rtthread學習筆記系列(3) -- FINSH模塊

文章目錄 3. FINSH模塊3.1MSH3.1.1初始化3.1.1.1FSymtab段3.1.1.2 宏 3.1.2遍歷FINSH命令3.1.3TAB補全實現3.1.3.1 msh_auto_complete3.1.3.2 msh_opt_auto_complete 3.1.4 TAB 子選項自動補全 3.2 SHELL3.2.1 finsh_system_init分配finsh結構體使用內存3.2.2 finsh_thread_ent…

Redis 知識速覽

文章目錄 1. Redis 簡介2. Redis 優缺點3. Redis 高性能4. Redis VM 機制5. Redis 數據類型6. 應用場景7. 持久化8. 過期策略9. 內存相關10. 線程模型11. 事務12. 集群 1. Redis 簡介 定義&#xff1a;Redis 是一個用 C 語言編寫的高性能非關系型&#xff08;NoSQL&#xff09…