C語(yǔ)言數(shù)組與地址、數(shù)組名到底是什么詳解
1.問題引出
案例:設(shè)計(jì)一個(gè)函數(shù),可以將整形數(shù)組的次序調(diào)換
例如:arr[5] = {1,2,3,4,5},輸出形式為:arr[5] = {5,4,3,2,1}.
案例代碼:
//能否可以正常排序? #include <stdio.h> void reverse(int* arr) { int len = sizeof(arr) / sizeof(arr[0]); int top = 0; int tail = len - 1; while (top < tail) { int tmp = 0; tmp = arr[top]; arr[top] = arr[tail]; arr[tail] = tmp; top++; tail--; } } int main() { int arr[] = { 1,2,3,4,5 }; int len = sizeof(arr) / sizeof(arr[0]); reverse(arr); for (int i = 0; i < len; i++) { printf("%d ", arr[i]); } return 0; }
我們來運(yùn)行一下:
我們發(fā)現(xiàn)結(jié)果并不是和我們想象的一樣輸出 5 4 3 2 1 ,而是對(duì)于原數(shù)組來說沒有變化,這是為什么呢?
2.分析錯(cuò)誤代碼
首先,按F10,點(diǎn)擊調(diào)試——>窗口——>監(jiān)視
在監(jiān)視窗口中輸入arr
,這時(shí)是運(yùn)行在主函數(shù)中,所以監(jiān)控的是主函數(shù)中的arr
這里能夠看到,arr
中儲(chǔ)存著5值
然后按F11進(jìn)入函數(shù)內(nèi)部,這時(shí)的監(jiān)視窗口是這樣:
這里有個(gè)技巧:需要在監(jiān)視中輸入arr,5
才能正常監(jiān)視到:
代碼再往下走,我們發(fā)現(xiàn)len
的值為1
但是int len = sizeof(arr) / sizeof(arr[0])
,len
的值應(yīng)該為arr
數(shù)組的長(zhǎng)度啊,應(yīng)該是5,為什么是1呢,這就需要了解數(shù)組名到底是什么
3.數(shù)組名是什么?
先探究數(shù)組名與數(shù)組元素首元素地址:
int main() { int arr[10] = { 0 }; printf("%p\n", arr); //數(shù)組名 printf("%p\n", &arr[0]);//數(shù)組首元素地址 return 0; }
結(jié)果:
所以得出結(jié)論:數(shù)組名是數(shù)組首元素的地址
但是有兩個(gè)例外:
1.sizeof(數(shù)組名),這里的數(shù)組名表示整個(gè)數(shù)組,計(jì)算的是整個(gè)數(shù)組的大小,單位是字節(jié)
2.&數(shù)組名,這里的數(shù)組名表示整個(gè)數(shù)組,&數(shù)組名取出的是數(shù)組的地址
驗(yàn)證一下sizeof(數(shù)組名):
int main() { int arr[10] = { 0 }; printf("%d", sizeof(arr)); return 0; }
結(jié)果:
數(shù)組長(zhǎng)度為10,int
類型一個(gè)元素4個(gè)字節(jié),所以輸出40,這就說明:
sizeof(數(shù)組名),數(shù)組名表示整個(gè)數(shù)組,計(jì)算的是整個(gè)數(shù)組的大小
驗(yàn)證 &數(shù)組名:
int main() { int arr[10] = { 0 }; printf("%p\n", arr); //數(shù)組名 printf("%p\n", &arr[0]);//數(shù)組首元素地址 printf("%p\n", &arr); //數(shù)組名取地址 return 0; }
結(jié)果:
發(fā)現(xiàn)這三個(gè)輸出的地址都相同,它們有什么區(qū)別呢?我們?cè)賮硖骄恳幌?/p>
arr
與·&arr[0]
一樣,都是指向數(shù)組首元素地址,他們的類型都是int*
而&arr
是整個(gè)數(shù)組的地址,&arr
的類型為:int(*)[10]
由于這個(gè)數(shù)組的地址由數(shù)組首元素地址開頭,所以這三個(gè)地址值從表面上看起來一樣,但可以從他們的指針類型去區(qū)別他們
再對(duì)比一下:
int main() { int arr[10] = { 0 }; printf("arr: %p\n", arr); printf("arr+1: %p\n", arr+1); printf("&arr[0]: %p\n", &arr[0]); printf("&arr[0]+1: %p\n", &arr[0]+1); printf("&arr: %p\n", &arr); printf("&arr+1 : %p\n", &arr+1); return 0; }
結(jié)果:
分析:
arr
與&arr[0]
都跳四個(gè)字節(jié),也就是數(shù)組下一個(gè)元素地址
而&arr
跳過了40個(gè)字節(jié),它跳過了整個(gè)數(shù)組
從這里的計(jì)算,也可以體會(huì)出arr
與&arr[0]
的類型是int*
,而&arr
的類型是int(*)[10]
4.錯(cuò)誤分析與修改
錯(cuò)誤分析:
前面的內(nèi)容我們知道了數(shù)組名是數(shù)組首元素地址,本質(zhì)上是個(gè)指針
所以在函數(shù)中,就需要用int*
去接收這個(gè)指針變量
void reverse(int* arr) { int len = sizeof(arr) / sizeof(arr[0]); int top = 0; int tail = len - 1; while (top < tail) { int tmp = 0; tmp = arr[top]; arr[top] = arr[tail]; arr[tail] = tmp; top++; tail--; } }
而在
reverse
內(nèi)部,sizeof(arr)
中的arr
被判定成了指針,而不是一個(gè)數(shù)組,所以sizeof(arr)
的值為4,sizeof(arr[0])
也為4,所以len
的值為1,而top=0
,tail = len-1 = 0
,top = tail
,根本進(jìn)不去下面的循環(huán),所以數(shù)組才不會(huì)改變
修改:
因?yàn)閿?shù)組作為參數(shù),它的長(zhǎng)度不可以在函數(shù)內(nèi)部被計(jì)算出來,所以就要在主函數(shù)中把數(shù)組的長(zhǎng)度計(jì)算出來,將數(shù)組長(zhǎng)度作為參數(shù)傳到函數(shù)中
#include <stdio.h> void reverse(int* arr,int len) { int top = 0; int tail = len - 1; while (top < tail) { int tmp = 0; tmp = arr[top]; arr[top] = arr[tail]; arr[tail] = tmp; top++; tail--; } } int main() { int arr[] = { 1,2,3,4,5 }; int len = sizeof(arr) / sizeof(arr[0]); reverse(arr,len); //兩個(gè)參數(shù),一個(gè)是數(shù)組首地址,一個(gè)是數(shù)組長(zhǎng)度 for (int i = 0; i < len; i++) { printf("%d ", arr[i]); } return 0; }
結(jié)果正確:
因?yàn)槲覀冎罃?shù)組名其實(shí)就是一個(gè)指針,所以在函數(shù)的參數(shù)列表中,可以使用int arr[]
去接受,也可以用int* arr
去接受收
//這兩種形式都可以 void reverse(int* arr,int len); void reverse(int arr[],int len);
5.總結(jié)
1.一般情況下,數(shù)組名就是數(shù)組首元素的地址
2.有兩個(gè)特殊情況:
- sizeof(數(shù)組名),這里的數(shù)組名表示整個(gè)數(shù)組,計(jì)算的是整個(gè)數(shù)組的大小。
- &數(shù)組名,這里的數(shù)組名表示整個(gè)數(shù)組,&數(shù)組名取出的是數(shù)組的地址。
3.有數(shù)組作為參數(shù)傳入的函數(shù)中,想要計(jì)算這個(gè)數(shù)組的長(zhǎng)度,在函數(shù)內(nèi)部做不到,需要在主函數(shù)中將數(shù)組長(zhǎng)度計(jì)算出來,將數(shù)組長(zhǎng)度作為參數(shù)傳入函數(shù)中,這才可以在函數(shù)中使用
到此這篇關(guān)于C語(yǔ)言數(shù)組與地址、數(shù)組名到底是什么的文章就介紹到這了,更多相關(guān)C語(yǔ)言數(shù)組與地址、數(shù)組名內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Matlab實(shí)現(xiàn)極坐標(biāo)堆疊柱狀圖的繪制
極坐標(biāo)堆疊圖也是風(fēng)玫瑰圖的常用形式,MATLAB的bar繪制的條形圖可以繪制成堆疊形式,但是并沒有一個(gè)自帶函數(shù)可以繪制極坐標(biāo)堆疊圖。本文將為大家提供Matlab繪制極坐標(biāo)堆疊柱狀圖的示例代碼,需要的可以參考一下2022-08-08c++回溯法解決1到9之間插入加減或空使運(yùn)算結(jié)果為100
編寫一個(gè)在1,2,…,9(順序不能變)數(shù)字之間插入+或-或什么都不插入,使得計(jì)算結(jié)果總是100的程序,并輸出所有的可能性。例如:1 + 2 + 34 – 5 + 67 – 8 + 9 = 1002021-10-10詳解C語(yǔ)言中雙向循環(huán)鏈表的實(shí)現(xiàn)
雙向鏈表也叫雙鏈表,是鏈表的一種,它的每個(gè)數(shù)據(jù)結(jié)點(diǎn)中都有兩個(gè)指針,分別指向直接后繼和直接前驅(qū)。本文將用C語(yǔ)言實(shí)現(xiàn)雙向循環(huán)鏈表,需要的可以參考一下2022-06-06C語(yǔ)言的abs()函數(shù)和div()函數(shù)你了解嗎
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的abs()函數(shù)和div()函數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02基于OpenCV讀取攝像頭實(shí)現(xiàn)單個(gè)人臉驗(yàn)證MFC程序
這篇文章主要為大家詳細(xì)介紹了基于OpenCV讀取攝像頭實(shí)現(xiàn)單個(gè)人臉驗(yàn)證MFC程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08Qt?QDateTime計(jì)算時(shí)間差的實(shí)現(xiàn)示例
本文主要介紹了Qt?QDateTime計(jì)算時(shí)間差的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04C++實(shí)現(xiàn)LeetCode(20.驗(yàn)證括號(hào))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(20.驗(yàn)證括號(hào)),本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07Dijkstra算法最短路徑的C++實(shí)現(xiàn)與輸出路徑
今天小編就為大家分享一篇關(guān)于Dijkstra算法最短路徑的C++實(shí)現(xiàn)與輸出路徑,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02C語(yǔ)言位段(位域)機(jī)制結(jié)構(gòu)體的特殊實(shí)現(xiàn)及解析
這篇文章主要為大家介紹了C語(yǔ)言位段位域機(jī)制結(jié)構(gòu)體的特殊實(shí)現(xiàn)講解有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-02-02