C語言多維數組

文章目錄

  • 多維數組
    • 數組名
    • 下標
    • 指向數組的指針
    • 作為函數參數的多維數組
  • 指針數組
  • 小結

多維數組

如果某個數組的維數超過1,它就被稱為多維數組,例如,下面這個聲明:

int matrix[6][10]

創建了一個包含60個元素的矩陣。但是,它是6行每行10個元素,還是10行每行6個元素?
為了回答這個問題,你需要從一個不同的視點觀察多維數組。考慮下列這些維數不斷增加的聲明:

int a;
int b[10];
int c[6][10];
int d[3][6][10];

a是個簡單的整數,接下來的那個聲明增加一個維數,所以b就是一個向量,它包含10個整形元素。

c只是在b的基礎上再增加一維,所以我們可以把c看做是一個包含6個元素的向量,只不過它的每個元素本身是一個包含10個整形元素的向量。換句話說,c是個一維數組的一維數組。d也是如此,它是一個包含三個元素的數組,每個元素都是包含6個元素的數組,而這6個元素中的每一個都是包含10個整形元素的數組,間接地說,d是一個3排6行10列的整形三維數組。

·

數組名

一維數組名的值是一個指針常量,它指向數組的第一個元素,它的類型是“指向元素類型的指針” 。多維數組也差不多簡單,唯一的區別是多維數組第1維的元素實際上是另一個數組。例如,下面這個聲明:

int matrix[3][10];

創建了matrix,它可以看做是一個一維數組,包含3個元素,只是每個元素恰好是包含10個整形元素的數組。
matrix這個名字的值是一個指向它第一個元素的指針,所以matrix是一個指向一個包含10個整型元素的數組的指針。

下標

如果要標識一個多維數組的某個元素,必須按照與數組聲明時相同的順序為每一維都提供一個下標,而且每個下標都單獨位于一對方括號內。在下面的聲明中:

int matrix[3][10];

表達式matrix[1][5]訪問下面這個元素
在這里插入圖片描述

但是,下標引用實際上只是間接訪問表達式的一種偽裝形式,即使在多維數組中也是如此,考慮下面這個表達式:

matrix

它的類型是“指向包含10個整型元素數組的指針”,它的值是
在這里插入圖片描述
表達式 matrix+1也是一個“指向10個整型元素數組的指針”,但它指向matrix的另一行
在這里插入圖片描述
為什么?因為1這個數值根據包含10個整型元素的數組的長度進行調制,所以它指向matrix下一行,如果對其執行間接訪問,就如下圖隨箭頭選擇中間的這個子數組
在這里插入圖片描述
所以表達式*(matrix+1)事實上標識了一個10個整型元素的子數組。數組名的值是個常量指針,它指向數組的第一個元素,在這個表達式中也是如此。它的類型是“指向整型的指針”,我們現在可以在下一維的上下文環境中顯示它的值。
在這里插入圖片描述
現在請拿穩你的帽子,猜猜下面這個表達式的結果是什么?

*(*(matrix+1)+5)

它所訪問的正是那個整型元素。如果它作為右值使用,你取得存儲于那個位置的值,如果它作為左值使用,這個位置將存儲一個新值。
這個看上去嚇人的表達式實際上正是我們的老朋友–下標,我們可以把表達式*(matrix+1)改寫成matrix[1],把這個下標表達式帶入原先的表達式,我們將得到:

*(matrix[1]+1);

這個表達式完全合法的,matrix[1]選定一個子數組,所以它的類型是一個指向整型的指針,我們對這個指針加上5,然后執行間接訪問操作。
但是,我們可以再次用下標代替間接訪問,所以這個表達式還可以寫出:

matrix[1][5]

指向數組的指針

下面這些聲明合法嗎?

int vector[10],*vp = vector;
int matrix[3][10],*mp = matrix;

第一個聲明是合法的。它為一個整型數組分配內存,并把vp聲明一個指向整型的指針,并把它初始化為指向vector數組的第一個元素。vector和vp具有相同的類型:指向整型的指針。但是第2個是非法的。它正確地創建了matrix數組,并把mp聲明為一個指向整型的指針。但是mp的初始化是不正確的,因為matrix并不是一個指向整型的指針,而是一個指向整型數組的指針。我們應該怎樣聲明一個指向整型數組的指針呢?

int (*p)[10];

下標引用的優先級高于間接訪問,但由于括號的存在,首先執行的還是間接訪問。所以p是個指針,但它指向什么呢?
接下來執行的是下標引用,所以p指向某種類型的數組。這個聲明表達式中并沒有更多的操作符,所以數組的每個元素都是整數。
聲明并沒有直接告訴你p是什么,但推斷它的類型并不困難,當我們對它執行間接訪問操作時,我們得到的是個數組,對該數組進行下標引用操作得到的是一個整型值。所以p是一個指向整型數組的指針

在聲明中加上初始化后是下面這個樣子:

int (*p)[10] = matrix;

它使p指向matrix的第一行。

作為函數參數的多維數組

作為函數參數的多維數組名的傳遞方式和一位數組名相同,實際傳遞的是個指向數組第一個元素的指針。但是,兩者之間的區別在于,多維數組的每個元素本身是另外一個數組,編譯器需要知道它的維數,以便為函數形參的下標表達式進行求值。這里有兩個例子,說明了它們之間的區別:

int vector[10];
... 
func1(vector);

參數vector得我類型是指向整型的指針,所以func1的原型可以是下面兩種的任何一種:

void funcl(int *vec);
void func1(int vec[]);

作用于vec上面的指針運算把整型的長度作為它的調整因子。
現在讓我們來觀察一個矩陣:

int matrix[3][10];
...
func2(matrix);

這里matrix的類型是指向包含10個整型元素數組的指針。func2的原型應該是怎樣的呢?你可以使用下面兩種形式中的任何一種:

void func2(int (*p)[10];
void func2(int mat[][10]);

在這個函數中,mat的第一個下標根據包含10個元素的整型數組的長度進行調整,接著第2個下標根據整型的長度進行調整,這和原先的matrix數組一樣。

在編寫一維數組形參的函數原型時,你既可以把它寫成數組的形式,也可以把它寫成指針的形式。但是,對于多維數組,只有第1維可以進行如此選擇。尤其是,把func2寫成下面這樣的原型是不正確的:

void func2(int**mat);

這個例子把mat聲明為一個指向整型指針的指針,它和指向數組的指針并不是一回事。

指針數組

除了類型之外,指針變量和其他變量很相似,正如你可以創建整型數組一樣,你也可以聲明指針數組。這里有一個例子:

int *api[10];

為了弄清楚這個復雜的聲明,我們假設它是一個表達式,并對它進行求值。

下標引用的優先級高于間接訪問,所以在這個表達式中,首先執行下標引用。因此,api是某種類型的數組,元素個數為10。在取得一個數組元素之后,隨機執行的是間接訪問操作,這個表達式不再有其他操作,所以它的結果是一個整型值。
那么api到底是什么東西?對數組的某個元素執行間接訪問操作后,我們得到一個整型值,所以api肯定是個數組,它的元素類型是指向整型的指針。

小結

一維數組的數組名指向第一個元素,類型是指向元素類型的指針。
二維數組的數組名是也指向它第一個元素,類型是指向數組的指針。
指針的指針是指向某種類型指針的指針,它和指向數組的指針并不是一回事。

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

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

相關文章

ubuntu路由器聯網_路由器及其協議簡介| 聯網

ubuntu路由器聯網路由器簡介 (Introduction to Router) Routers are network layer devices. Data on the network layer is known as packets. Routers work to forward packets from one network to another. Routers also maintain the address table. 路由器是網絡層設備。…

XPath學習:軸(5)——descendant-or-self

XPath 是一門在 XML 文檔中查找信息的語言。XPath 可用來在 XML 文檔中對元素和屬性進行遍歷。 XPath 是 W3C XSLT 標準的主要元素,并且 XQuery 和 XPointer 同時被構建于 XPath 表達之上。 推薦一個挺不錯的網站:http://www.zvon.org/xxl/XPathTutorial…

linux設備驅動開發---平臺設備驅動程序

文章目錄1 平臺驅動程序2 平臺設備2.1 資源和平臺數據1 設備配置---廢棄的舊方法資源平臺數據聲明平臺設備2 設備配置---推薦的新方法3 設備、驅動程序和總線匹配OF風格ACPIID表匹配匹配平臺設備的名字和平臺驅動的名字平臺設備和平臺驅動程序如何匹配4 Platfrom架構驅動程序有…

標題:乘積尾零

標題:乘積尾零 如下的10行數據,每行有10個整數,請你求出它們的乘積的末尾有多少個零? 5650 4542 3554 473 946 4114 3871 9073 90 4329 2758 7949 6113 5659 5245 7432 3051 4434 6704 3594 9937 1173 6866 3397 4759 7557 3070…

Robots.txt指南

Robots.txt指南當搜索引擎訪問一個網站時,它首先會檢查該網站的根域下是否有一個叫做robots.txt的純文本文件。Robots.txt文件用于限定搜索引擎對其 網站的訪問范圍,即告訴搜索引擎網站中哪些文件是允許它進行檢索(下載)的。這就是大家在網絡上常看到的“…

fwrite函數的用法示例_C語言中的fwrite()函數(帶有示例)

fwrite函數的用法示例C中的fwrite()函數 (fwrite() function in C) Prototype: 原型: size_t fwrite(void *buffer, size_t length, size_t count, FILE *filename);Parameters: 參數: void *buffer, size_t length, size_t count, FILE *filenameRetu…

標題:遞增三元組

標題&#xff1a;遞增三元組 給定三個整數數組 A [A1, A2, … AN], B [B1, B2, … BN], C [C1, C2, … CN]&#xff0c; 請你統計有多少個三元組(i, j, k) 滿足&#xff1a; 1 < i, j, k < NAi < Bj < Ck 【輸入格式】 第一行包含一個整數N。 第二行包含N個整…

伙伴算法、slab機制、內存管理函數

文章目錄1 伙伴算法頁框操作alloc_pages()2 slabslab機制要解決的問題使用高速緩存3 內存管理函數kmallockzallocvmallocvzalloc區別參考文章內核使用struct page結構體描述每個物理頁&#xff0c;也叫頁框。內核在很多情況下&#xff0c;需要申請連續的頁框&#xff0c;而且數…

eval 函數 代替函數_eval()函數以及JavaScript中的示例

eval 函數 代替函數eval()函數 (eval() function) eval() function is a predefined global function in JavaScript and it is used to evaluate (execute) an expression, which is passed to the function as a parameter. It can also evaluate any JavaScript code. eval(…

F# ≥ C#(活動模式 和枚舉)

F#提供了一個叫"活動模式"的有趣功能。它把輸入的數據轉換成其他不同的東西。 一個有趣的使用實例就是代替枚舉。但我編程枚舉的時候&#xff0c;我總不高興去鏈接枚舉項到它的定義。例如&#xff0c;下面的枚舉定義了 數字枚舉&#xff0c; enum Numbers{Odd,Even,}…

關于java的classpath設置

今天晚上實驗室的另一個人在編譯一個java程序&#xff0c;需要用到一個jar文件&#xff0c;所以在命令行編譯的時候需要添加jar的路徑&#xff0c;例如&#xff1a; java -classpath demo.jar hello 但是設置了path之后java就不會搜索當前目錄&#xff0c;也就是所如果hello在當…

C語言uthash的用法

文章目錄1 定義一個哈希表鍵值UT_hash_handle2 哈希操作聲明添加查找刪除獲取哈希表中元素個數迭代排序3 案例鍵的使用官網解釋&#xff1a;https://troydhanson.github.io/uthash/userguide.html 在使用之前&#xff0c;我們必須包含uthash.h的頭文件&#xff0c;你需要將該頭…

Javascript Paste Keyboard Shortcuts Hijack

author : kj021320 team : I.S.T.O 這樣的攻擊手段也算是極其無恥 猥瑣之極! 所以防御措施一定要做好 首先說一下通過Javascript Paste Keyboard Shortcuts Hijack能做什么???能夠讀取你本地機器任何文件! 沒錯!也就是說 你中了任何一個XSS 加上你按了粘貼快捷鍵后,你就有可…

python 生成器表達式_Python中的列表理解與生成器表達式

python 生成器表達式The list is a collection of different types of elements and there are many ways of creating a list in Python. 該列表是不同類型元素的集合&#xff0c;并且有許多方法可以在Python中創建列表。 清單理解 (List Comprehension) List comprehension…

Javaweb---監聽器

1.什么是監聽器 監聽器就是監聽某個對象的狀態變化的組件。 事件源&#xff1a;被監聽的對象 ----- 三個域對象 request session servletContext 監聽器&#xff1a;監聽事件源對象 事件源對象的狀態的變化都會觸發監聽器 ---- 62 注冊監聽器&#xff1a;將監聽器與事件源進行…

Linux中的Ramdisk和Initrd

Ramdisk簡介先簡單介紹一下ramdisk&#xff0c;Ramdisk是虛擬于RAM中的盤(Disk)。對于用戶來說&#xff0c;能把RAM disk和通常的硬盤分區&#xff08;如/dev/hda1&#xff09;同等對待來使用&#xff0c;例如&#xff1a;redice # mkfs.ext2 /dev/ram0mke2fs 1.38 (30-Jun-200…

slab下kmalloc內核函數實現

文章目錄kmalloc的整體實現獲取高速緩存高速緩存獲取index總結https://blog.csdn.net/qq_41683305/article/details/124554490&#xff0c;在這篇文章中&#xff0c;我們介紹了伙伴算法、slab機制和常見的內存管理函數&#xff0c;接下來&#xff0c;我們看看kmalloc內核函數的…

PHP array_merge_recursive()函數與示例

PHP array_merge_recursive()函數 (PHP array_merge_recursive() function) array_merge_recursive() function is used to merge two or more arrays, it returns a new array with merged elements. The only difference between array_merge() and array_merge_recursive() …

標題:三羊獻瑞

標題&#xff1a;觀察下面的加法算式&#xff1a; 其中&#xff0c;相同的漢字代表相同的數字&#xff0c;不同的漢字代表不同的數字。 請你填寫“三羊獻瑞”所代表的4位數字&#xff08;答案唯一&#xff09;&#xff0c;不要填寫任何多余內容。 思路分析&#xff1a; 首先…

hdu 1069

地址&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1069 題意&#xff1a;給定若干個木塊長寬高&#xff0c;長寬高可以自己調整&#xff0c;求堆積起來最高的高度。 mark&#xff1a;枚舉所有木塊長寬高可能情況&#xff0c;簡單dp。 代碼&#xff1a; #include <…