C語言例題講解指針與數(shù)組
1.概要復(fù)習(xí)
本篇的內(nèi)容主要圍繞指針與數(shù)組、指針與字符串等之間的關(guān)系,以及進一步理解sizeof 、strlen 的使用與意義。
數(shù)組是指具有相同類型元素的集合,字符串常量是一個指向在連續(xù)空間里存放的字符的首字符的地址的指針。我們會在下面理解數(shù)組與字符串?dāng)?shù)組的不同。
sizeof 是一個操作符,是計算類型空間大小的。strlen 是針對字符串的庫函數(shù),用來求字符串的長度。
對于數(shù)組來說,數(shù)組名都是首元素地址,除了這兩種情況外:
- sizeof(數(shù)組名)——sizeof內(nèi)部單獨放置數(shù)組名表整個數(shù)組
- &數(shù)組名——對數(shù)組名進行取地址操作表取出整個數(shù)組的地址
2.指針與數(shù)組筆試題
我們的目的是求下面各個 printf 語句輸出什么。
2.1一維數(shù)組
#include <stdio.h> int main() { int a[] = { 1,2,3,4 }; printf("%d\n", sizeof(a)); printf("%d\n", sizeof(a + 0)); printf("%d\n", sizeof(*a)); printf("%d\n", sizeof(a + 1)); printf("%d\n", sizeof(a[1])); printf("%d\n", sizeof(&a)); printf("%d\n", sizeof(*&a)); printf("%d\n", sizeof(&a + 1)); printf("%d\n", sizeof(&a[0])); printf("%d\n", sizeof(&a[0] + 1)); return 0; }
#include <stdio.h> int main() { int a[] = { 1,2,3,4 }; printf("%d\n", sizeof(a)); //sizeof 內(nèi)部單獨放置數(shù)組名,計算整個數(shù)組的大小,結(jié)果為 4(int類型)*4(元素個數(shù))=16 printf("%d\n", sizeof(a + 0)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,此時數(shù)組名表首元素地址,a+0 依然表示首元素地址 //故 sizeof 計算一個地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(*a)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,此時數(shù)組名表首元素地址,*a 表對該地址解引用 //即可得到 a 數(shù)組的第一個元素,大小為 4(int類型) printf("%d\n", sizeof(a + 1)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,此時數(shù)組名表首元素地址,a+1 表第二個元素地址 //故 sizeof 計算一個地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(a[1])); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,a[1] 表數(shù)組的第二個元素,此寫法可轉(zhuǎn)置為 *(a+1) //即計算的結(jié)果是第二個元素的類型大小,即 4(int類型) printf("%d\n", sizeof(&a)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,而是放置了 &a ,表取出整個數(shù)組的地址 //故 sizeof 計算一個地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(*&a)); //sizeof 內(nèi)部雖然看似沒有單獨放置數(shù)組名,但是通過 &a 取出整個數(shù)組地址 //然后通過 * 找到整個地址,與 sizeof(a) 沒有差別 //故這里的 sizeof 計算的也是整個數(shù)組的大小,即 4(int類型)*4(元素個數(shù))=16 printf("%d\n", sizeof(&a + 1)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,&a+1 表取出整個數(shù)組的地址,并向后跳躍一個數(shù)組類型的大小 //即此時的地址是指向元素 4 的后面一塊 int 類型的內(nèi)存空間 //故 sizeof 計算地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(&a[0])); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,&a[0] 表取出數(shù)組第一個元素的地址 //故 sizeof 計算地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(&a[0] + 1)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,&a[0]+1 表取出數(shù)組第一個元素地址并向后跳躍一個 int 類型的大小 //故 sizeof 計算的是地址(指針)的大小為 4 or 8 return 0; }
2.2字符數(shù)組
#include <stdio.h> int main() { char arr[] = { 'a','b','c','d','e','f' }; printf("%d\n", sizeof(arr)); printf("%d\n", sizeof(arr + 0)); printf("%d\n", sizeof(*arr)); printf("%d\n", sizeof(arr[1])); printf("%d\n", sizeof(&arr)); printf("%d\n", sizeof(&arr + 1)); printf("%d\n", sizeof(&arr[0] + 1)); printf("%d\n", strlen(arr)); printf("%d\n", strlen(arr + 0)); printf("%d\n", strlen(*arr)); printf("%d\n", strlen(arr[1])); printf("%d\n", strlen(&arr)); printf("%d\n", strlen(&arr + 1)); printf("%d\n", strlen(&arr[0] + 1)); return 0; }
#include <stdio.h> int main() { char arr[] = { 'a','b','c','d','e','f' };//非字符串!?。。。?! printf("%d\n", sizeof(arr)); //sizeof 內(nèi)部單獨放置數(shù)組名,故計算的是整個數(shù)組的大小 //即大小為 1(char類型)*6(元素個數(shù))=6 printf("%d\n", sizeof(arr + 0)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,arr 表數(shù)組首元素地址,arr+0 亦表示首元素地址 //故 sizeof 計算地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(*arr)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,arr 表數(shù)組首元素地址,*arr 表對該地址解引用 //便得到數(shù)組第一個元素 'a' ,故大小為 1(char類型) printf("%d\n", sizeof(arr[1])); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,arr[1] 表數(shù)組第二個元素,即 'b' //故大小為 1(char類型) printf("%d\n", sizeof(&arr)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,&arr 表取出整個數(shù)組的地址 //故 sizeof 計算的地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(&arr + 1)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,&arr+1 表取出整個數(shù)組的地址并向后跳躍一個數(shù)組類型的大小 //即指向元素 'f' 后一個 char 類型的空間 //故 sizeof 計算的是地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(&arr[0] + 1)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,&arr[0]+1 表取出數(shù)組一個元素的地址并向后跳躍一個 char 類型的大小 //故 sizeof 計算的地址(指針)的大小為 4 or 8 printf("%d\n", strlen(arr)); //strlen 不是 sizeof ,故 arr 表數(shù)組首元素地址,strlen 會以此地址開始向后尋找 '\0' //但此數(shù)組并不包含 '\0' ,故 strlen 的返回值為隨機值 printf("%d\n", strlen(arr + 0)); //strlen 不是 sizeof ,arr+0 表首元素地址,strlen 的返回值也是一個隨機值 printf("%d\n", strlen(*arr)); //strlen 不是 sizeof ,*arr 表對數(shù)組首元素地址解引用,得到字符 'a' ,其 ASCLL 碼值為 97 //strlen 會以 97 為起始地址向后尋找 '\0' //但個人理解認為:97 是一個沒有初始化的指針(地址),即野指針 //故這里會報錯 printf("%d\n", strlen(arr[1])); //arr[1] 表數(shù)組的第二個元素 'b' ,其 ASCLL 碼值為 98 //strlen 會以 98 為起始地址向后尋找 '\0' //但個人理解認位:98 是一個沒有初始化的指針(地址),即野指針 //故這里依然會報錯 printf("%d\n", strlen(&arr)); //&arr 表取出整個數(shù)組的地址,strlen 會以此作為起始地址向后尋找 '\0' //這里需要注意,在 strlen 的函數(shù)聲明當(dāng)中,參數(shù)是一個 char* 類型的指針 //也就是我們雖然傳參時傳了一個數(shù)組指針,但是 strlen 接收時會自動強轉(zhuǎn)為 char* 類型指針 //故數(shù)組并不包含 '\0' ,strlen 的返回值是一個隨機值 printf("%d\n", strlen(&arr + 1)); //&arr+1 表取出整個數(shù)組的地址并向后跳躍一個數(shù)組類型的大小 //即指向了元素 'f' 的后一塊 char 類型的空間 //strlen 會以此地址作為起始地址向后尋找 '\0' //但因我們無法確定 '\0' 的位置,所以 strlen 的返回值是一個隨機值 printf("%d\n", strlen(&arr[0] + 1)); //&arr[0]+1 表取出數(shù)組首元素地址并向后跳躍一個 char 類型的大小 //即指向了元素 'b' ,strlen 會以此地址作為起始地址向后尋找 '\0' //但數(shù)組中并不包含 '\0' ,故 strlen 的返回值是一個隨機值 return 0; }
我們把報錯的兩條語句注釋掉:
2.3字符串?dāng)?shù)組
#include <stdio.h> int main() { char arr[] = "abcdef"; printf("%d\n", sizeof(arr)); printf("%d\n", sizeof(arr + 0)); printf("%d\n", sizeof(*arr)); printf("%d\n", sizeof(arr[1])); printf("%d\n", sizeof(&arr)); printf("%d\n", sizeof(&arr + 1)); printf("%d\n", sizeof(&arr[0] + 1)); printf("%d\n", strlen(arr)); printf("%d\n", strlen(arr + 0)); printf("%d\n", strlen(*arr)); printf("%d\n", strlen(arr[1])); printf("%d\n", strlen(&arr)); printf("%d\n", strlen(&arr + 1)); printf("%d\n", strlen(&arr[0] + 1)); return 0; }
#include <stdio.h> int main() { char arr[] = "abcdef";//注意數(shù)組里面放的是字符串?。?! printf("%d\n", sizeof(arr)); //sizeof 內(nèi)部單獨放置數(shù)組名,即計算整個數(shù)組的大小 //大小為 1(char類型)*7(元素個數(shù))=7 printf("%d\n", sizeof(arr + 0)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,arr+0 表數(shù)組首元素地址 //故 sizeof 計算地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(*arr)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,*arr 表對數(shù)組首元素地址解引用 //即得到字符 'b' ,故大小為 1(char類型) printf("%d\n", sizeof(arr[1])); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,arr[1] 表數(shù)組第二個元素即字符 'b' //故大小為 1(char類型) printf("%d\n", sizeof(&arr)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,&arr 表對整個數(shù)組取地址 //故 sizeof 計算的地址(指針)大小為 4 or 8 printf("%d\n", sizeof(&arr + 1)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,&arr+1 表取出整個數(shù)組地址并向后跳躍一個數(shù)組類型大小 //即指向元素 '\0' 后面一塊數(shù)組類型大小的空間 //故 sizeof 計算的地址(指針)大小為 4 or 8 printf("%d\n", sizeof(&arr[0] + 1)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,&arr[0]+1 表取出數(shù)組首元素地址并向后跳躍一個 char 類型大小 //即指向數(shù)組第二個元素 //故 sizeof 計算的地址(指針)大小為 4 or 8 printf("%d\n", strlen(arr)); //strlen 不是 sizeof ,arr 表數(shù)組首元素地址,strlen 會以此為起始地址向后尋找 '\0' //因為此數(shù)組包含 '\0' ,故 strlen 的返回值為 6 printf("%d\n", strlen(arr + 0)); //arr+0 表數(shù)組首元素地址,strlen 會以此地址為起始地址向后尋找 '\0' //因為此數(shù)組包含 '\0' ,故 strlen 的返回值為 6 printf("%d\n", strlen(*arr)); //*arr 表對數(shù)組首元素地址解引用,得到字符 'a' ,其 ASCLL 碼值為 97 //故 strlen 會以此地址為起始地址向后尋找 '\0' //但個人理解認位: 97 是一個沒有初始化的指針(地址),即野指針 //故這里會報錯 printf("%d\n", strlen(arr[1])); //arr[1] 表數(shù)組第二個元素,即字符 'b' ,其 ASCLL 碼值為 98 //strlen 會以此地址會起始地址向后尋找 '\0' //但個人理解認位:98 是一個沒有初始化的指針(地址),即野指針 //故這里會報錯 printf("%d\n", strlen(&arr)); //&arr 表取出整個數(shù)組的地址,但觀察 strlen 函數(shù)的聲明可以發(fā)現(xiàn) //strlen 的函數(shù)參數(shù)是一個 char* 類型的指針 //即我們傳參傳進去的是一個數(shù)組指針,當(dāng) strlen 接收的時候,會將其強轉(zhuǎn)為字符指針 //故 strlen 會以數(shù)組首元素地址為起始地址,向后尋找 '\0' //因為數(shù)組包含 '\0' ,故 strlen 的返回值為 6 printf("%d\n", strlen(&arr + 1)); //&arr+1 表取出整個數(shù)組的地址并向后跳躍一個數(shù)組類型大小 //即指向 '\0' 后一塊數(shù)組類型的空間 //strlen 會以此地址為起始地址向后尋找 '\0' //但我們無法確定 '\0' 的具體位置,所以 strlen 會返回一個隨機值 printf("%d\n", strlen(&arr[0] + 1)); //&arr[0]+1 表取出數(shù)組首元素地址并向后跳躍一個 char 類型的大小 //即指向了數(shù)組第二個元素的地址 //strlen 會以此地址作為起始地址向后尋找 '\0' //故 strlen 的返回值為 5 return 0; }
我們把報錯的語句注釋掉:
2.4字符串指針
#include <stdio.h> int main() { char* p = "abcdef";//p 變量存放的是字符串常量的首元素地址 printf("%d\n", sizeof(p)); //sizeof 計算地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(p + 1)); //p+1 表字符串常量的第二個元素的地址 //故 sizeof 計算的地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(*p)); //*p 表對字符串常量首元素地址解引用。得到字符 'a' //故計算的大小為 1(char類型) printf("%d\n", sizeof(p[0])); //p[0] 可改寫成 *(p+0) ,表對字符串常量首元素地址解引用,得到字符 'a' //即計算的大小為 1(char類型) printf("%d\n", sizeof(&p)); //&p 表對 char* 類型指針取地址 //故 sizeof 計算的地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(&p + 1)); //&p+1 表對 char* 類型指針變量 p 取地址并向后跳躍一個 char 類型的大小 //指向的空間是未知的 //但 sizeof 計算的地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(&p[0] + 1)); //&p[0]+1 可改寫成 &(*(p+0))+1 ,表取出字符串常量的首元素地址并向后跳躍一個 char 類型的大小 //即指向了字符 'b' //故 sizeof 計算的地址(指針)的大小為 4 or 8 printf("%d\n", strlen(p)); //strlen 不是 sizeof ,p表字符串首元素地址 //strlen 以此地址為起始地址,向后尋找 '\0' //故 strlen 的返回值為 6 printf("%d\n", strlen(p + 1)); //p+1 表字符串常量的第二個元素的地址,strlen 會以此為地址向后尋找 '\0' //故 strlen 的返回值為 5 printf("%d\n", strlen(*p)); //*p 表字符串常量首元素,即字符 'a',strlen 會以此為地址向后尋找 '\0' //但個人理解人為:'a' 的 ASCLL 碼值為 97 ,但 97 是一個沒有被初始化的指針(地址),即野指針 //故這里會報錯 printf("%d\n", strlen(p[0])); //p[0] 可改寫成 *(p+0) ,表字符串常量首元素,即字符 'a',其 ASCLL 碼值為 97 //strlen 會以此地址為起始地址向后尋找 '\0' //但個人理解認位:97 是一個沒有被初始化的指針(地址),即野指針 //故這里會報錯 printf("%d\n", strlen(&p)); //&p 表取出 char* 類型指針變量的地址,strlen 以此地址為起始地址向后尋找 '\0' //但我們無法確定 '\0' 的位置 //故 strlen 會返回一個隨機值 printf("%d\n", strlen(&p + 1)); //&p+1 表取出 char* 類型指針變量的地址并向后跳躍一個 char 類型的大小,strlen 以此地址為起始地址向后尋找 '\0' //但我們無法確定 '\0'的位置,故 strlen 的返回值會返回一個隨機值 printf("%d\n", strlen(&p[0] + 1)); //*p{0}+1 可改寫為 &(*(p+0))+1 ,表取出字符串常量首元素地址并向后跳躍一個 char 類型的大小 //即指向了字符串常量的第二個元素的地址,strlen 會以此地址為起始地址向后尋找 '\0' //故 strlen 的返回值為 5 return 0; }
我們對報錯的兩條語句注釋:
2.5二維數(shù)組
#include <stdio.h> int main() { int a[3][4] = { 0 }; printf("%d\n", sizeof(a)); //sizeof 內(nèi)部放置的是數(shù)組名,故計算整個數(shù)組的大小 //即大小為 4(int類型)*12(元素個數(shù))=48 printf("%d\n", sizeof(a[0][0])); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,a[0][p] 表數(shù)組首元素 //故 sizeof 的計算值為 4(int類型) printf("%d\n", sizeof(a[0])); //sizeof 內(nèi)部放置的看似不是單獨的數(shù)組名,但 a[0] 表數(shù)組的第一個元素 //此元素也是一個數(shù)組 //故 sizeof 計算的大小為 4(int類型)*4(元素個數(shù))=16 printf("%d\n", sizeof(a[0] + 1)); //sizeof 內(nèi)部放置的不是單獨的數(shù)組名,a[0] 表二維數(shù)組的第一個元素,即拿到了一個數(shù)組 //a[0]+1 表二維數(shù)組的第一個數(shù)組元素的地址并向后跳躍一個 int 類型的大小 //故 sizeof 計算的地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(*(a[0] + 1))); //*(a[0]+1) 表對二維數(shù)組的第一個數(shù)組元素的地址并向后跳躍一個 int 類型的大小的解引用 //即找到了二維數(shù)組中的某一個元素 //故 sizeof 計算的大小為 4(int類型) printf("%d\n", sizeof(a + 1)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,a+1 表二維數(shù)組的首元素地址并向后跳躍一個一維數(shù)組類型的大小 //即指向了二維數(shù)組的第二個數(shù)組元素的地址 //故 sizeof 計算的地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(*(a + 1))); //*(a+1) 表對二維數(shù)組的首元素地址并向后跳躍一個一維數(shù)組類型的大小的解引用 //即得到了二維數(shù)組的第二個元素 //此元素為一個一維數(shù)組,故 sizeof 計算的大小為 4(int類型)*4(元素個數(shù))=16 printf("%d\n", sizeof(&a[0] + 1)); //&a[0]+1 表二維數(shù)組的首元素取地址并向后跳躍一個一維數(shù)組的類型大小 //指向了二維數(shù)組的第二個元素 //故 sizeof 計算的地址(指針)的大小為 4 or 8 printf("%d\n", sizeof(*(&a[0] + 1))); //*(&a[0]+1) 表對二維數(shù)組的首元素取地址并向后跳躍一個一維數(shù)組的類型大小的解引用 //即得到了二維數(shù)組的第二個元素 //此元素是一個一維數(shù)組,故 sizeof 計算的大小的 4(int類型)*4(元素個數(shù))=16 printf("%d\n", sizeof(*a)); //sizeof 內(nèi)部沒有單獨放置數(shù)組名,*a 表對二維數(shù)組首元素地址解引用 //得到一個一維數(shù)組 //故 sizeof 計算的大小為 4(int類型)*4(元素個數(shù))=16 printf("%d\n", sizeof(a[3])); //a[3] 表二維數(shù)組的第三個元素 //需要說明的是,sizeof 只對類型感興趣 //也就是說,二維數(shù)組雖然不存在第三個元素,但它的類型依舊是二維數(shù)組 //故 sizeof 計算的是 4(int類型)*4(元素個數(shù))=16 return 0; }
到此這篇關(guān)于C語言例題講解指針與數(shù)組的文章就介紹到這了,更多相關(guān)C語言指針與數(shù)組內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ leetcode之刪除并獲得點數(shù)的示例代碼
這篇文章主要介紹了C++ leetcode之刪除并獲得點數(shù)的示例代碼,本文給大家分享問題解析及解決方案,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-05-05C++數(shù)據(jù)結(jié)構(gòu)關(guān)于棧迷宮求解示例
這篇文章主要為大家介紹了C++數(shù)據(jù)結(jié)構(gòu)關(guān)于棧的迷宮求解示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2021-11-11