網站首頁 編程語言 正文
1.概要復習
本篇的內容主要圍繞指針與數組、指針與字符串等之間的關系,以及進一步理解sizeof 、strlen 的使用與意義。
數組是指具有相同類型元素的集合,字符串常量是一個指向在連續空間里存放的字符的首字符的地址的指針。我們會在下面理解數組與字符串數組的不同。
sizeof 是一個操作符,是計算類型空間大小的。strlen 是針對字符串的庫函數,用來求字符串的長度。
對于數組來說,數組名都是首元素地址,除了這兩種情況外:
- sizeof(數組名)——sizeof內部單獨放置數組名表整個數組
- &數組名——對數組名進行取地址操作表取出整個數組的地址
2.指針與數組筆試題
我們的目的是求下面各個 printf 語句輸出什么。
2.1一維數組
#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 內部單獨放置數組名,計算整個數組的大小,結果為 4(int類型)*4(元素個數)=16
printf("%d\n", sizeof(a + 0));
//sizeof 內部沒有單獨放置數組名,此時數組名表首元素地址,a+0 依然表示首元素地址
//故 sizeof 計算一個地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(*a));
//sizeof 內部沒有單獨放置數組名,此時數組名表首元素地址,*a 表對該地址解引用
//即可得到 a 數組的第一個元素,大小為 4(int類型)
printf("%d\n", sizeof(a + 1));
//sizeof 內部沒有單獨放置數組名,此時數組名表首元素地址,a+1 表第二個元素地址
//故 sizeof 計算一個地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(a[1]));
//sizeof 內部沒有單獨放置數組名,a[1] 表數組的第二個元素,此寫法可轉置為 *(a+1)
//即計算的結果是第二個元素的類型大小,即 4(int類型)
printf("%d\n", sizeof(&a));
//sizeof 內部沒有單獨放置數組名,而是放置了 &a ,表取出整個數組的地址
//故 sizeof 計算一個地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(*&a));
//sizeof 內部雖然看似沒有單獨放置數組名,但是通過 &a 取出整個數組地址
//然后通過 * 找到整個地址,與 sizeof(a) 沒有差別
//故這里的 sizeof 計算的也是整個數組的大小,即 4(int類型)*4(元素個數)=16
printf("%d\n", sizeof(&a + 1));
//sizeof 內部沒有單獨放置數組名,&a+1 表取出整個數組的地址,并向后跳躍一個數組類型的大小
//即此時的地址是指向元素 4 的后面一塊 int 類型的內存空間
//故 sizeof 計算地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(&a[0]));
//sizeof 內部沒有單獨放置數組名,&a[0] 表取出數組第一個元素的地址
//故 sizeof 計算地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(&a[0] + 1));
//sizeof 內部沒有單獨放置數組名,&a[0]+1 表取出數組第一個元素地址并向后跳躍一個 int 類型的大小
//故 sizeof 計算的是地址(指針)的大小為 4 or 8
return 0;
}
2.2字符數組
#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 內部單獨放置數組名,故計算的是整個數組的大小
//即大小為 1(char類型)*6(元素個數)=6
printf("%d\n", sizeof(arr + 0));
//sizeof 內部沒有單獨放置數組名,arr 表數組首元素地址,arr+0 亦表示首元素地址
//故 sizeof 計算地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(*arr));
//sizeof 內部沒有單獨放置數組名,arr 表數組首元素地址,*arr 表對該地址解引用
//便得到數組第一個元素 'a' ,故大小為 1(char類型)
printf("%d\n", sizeof(arr[1]));
//sizeof 內部沒有單獨放置數組名,arr[1] 表數組第二個元素,即 'b'
//故大小為 1(char類型)
printf("%d\n", sizeof(&arr));
//sizeof 內部沒有單獨放置數組名,&arr 表取出整個數組的地址
//故 sizeof 計算的地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(&arr + 1));
//sizeof 內部沒有單獨放置數組名,&arr+1 表取出整個數組的地址并向后跳躍一個數組類型的大小
//即指向元素 'f' 后一個 char 類型的空間
//故 sizeof 計算的是地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(&arr[0] + 1));
//sizeof 內部沒有單獨放置數組名,&arr[0]+1 表取出數組一個元素的地址并向后跳躍一個 char 類型的大小
//故 sizeof 計算的地址(指針)的大小為 4 or 8
printf("%d\n", strlen(arr));
//strlen 不是 sizeof ,故 arr 表數組首元素地址,strlen 會以此地址開始向后尋找 '\0'
//但此數組并不包含 '\0' ,故 strlen 的返回值為隨機值
printf("%d\n", strlen(arr + 0));
//strlen 不是 sizeof ,arr+0 表首元素地址,strlen 的返回值也是一個隨機值
printf("%d\n", strlen(*arr));
//strlen 不是 sizeof ,*arr 表對數組首元素地址解引用,得到字符 'a' ,其 ASCLL 碼值為 97
//strlen 會以 97 為起始地址向后尋找 '\0'
//但個人理解認為:97 是一個沒有初始化的指針(地址),即野指針
//故這里會報錯
printf("%d\n", strlen(arr[1]));
//arr[1] 表數組的第二個元素 'b' ,其 ASCLL 碼值為 98
//strlen 會以 98 為起始地址向后尋找 '\0'
//但個人理解認位:98 是一個沒有初始化的指針(地址),即野指針
//故這里依然會報錯
printf("%d\n", strlen(&arr));
//&arr 表取出整個數組的地址,strlen 會以此作為起始地址向后尋找 '\0'
//這里需要注意,在 strlen 的函數聲明當中,參數是一個 char* 類型的指針
//也就是我們雖然傳參時傳了一個數組指針,但是 strlen 接收時會自動強轉為 char* 類型指針
//故數組并不包含 '\0' ,strlen 的返回值是一個隨機值
printf("%d\n", strlen(&arr + 1));
//&arr+1 表取出整個數組的地址并向后跳躍一個數組類型的大小
//即指向了元素 'f' 的后一塊 char 類型的空間
//strlen 會以此地址作為起始地址向后尋找 '\0'
//但因我們無法確定 '\0' 的位置,所以 strlen 的返回值是一個隨機值
printf("%d\n", strlen(&arr[0] + 1));
//&arr[0]+1 表取出數組首元素地址并向后跳躍一個 char 類型的大小
//即指向了元素 'b' ,strlen 會以此地址作為起始地址向后尋找 '\0'
//但數組中并不包含 '\0' ,故 strlen 的返回值是一個隨機值
return 0;
}
我們把報錯的兩條語句注釋掉:
2.3字符串數組
#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";//注意數組里面放的是字符串!!!
printf("%d\n", sizeof(arr));
//sizeof 內部單獨放置數組名,即計算整個數組的大小
//大小為 1(char類型)*7(元素個數)=7
printf("%d\n", sizeof(arr + 0));
//sizeof 內部沒有單獨放置數組名,arr+0 表數組首元素地址
//故 sizeof 計算地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(*arr));
//sizeof 內部沒有單獨放置數組名,*arr 表對數組首元素地址解引用
//即得到字符 'b' ,故大小為 1(char類型)
printf("%d\n", sizeof(arr[1]));
//sizeof 內部沒有單獨放置數組名,arr[1] 表數組第二個元素即字符 'b'
//故大小為 1(char類型)
printf("%d\n", sizeof(&arr));
//sizeof 內部沒有單獨放置數組名,&arr 表對整個數組取地址
//故 sizeof 計算的地址(指針)大小為 4 or 8
printf("%d\n", sizeof(&arr + 1));
//sizeof 內部沒有單獨放置數組名,&arr+1 表取出整個數組地址并向后跳躍一個數組類型大小
//即指向元素 '\0' 后面一塊數組類型大小的空間
//故 sizeof 計算的地址(指針)大小為 4 or 8
printf("%d\n", sizeof(&arr[0] + 1));
//sizeof 內部沒有單獨放置數組名,&arr[0]+1 表取出數組首元素地址并向后跳躍一個 char 類型大小
//即指向數組第二個元素
//故 sizeof 計算的地址(指針)大小為 4 or 8
printf("%d\n", strlen(arr));
//strlen 不是 sizeof ,arr 表數組首元素地址,strlen 會以此為起始地址向后尋找 '\0'
//因為此數組包含 '\0' ,故 strlen 的返回值為 6
printf("%d\n", strlen(arr + 0));
//arr+0 表數組首元素地址,strlen 會以此地址為起始地址向后尋找 '\0'
//因為此數組包含 '\0' ,故 strlen 的返回值為 6
printf("%d\n", strlen(*arr));
//*arr 表對數組首元素地址解引用,得到字符 'a' ,其 ASCLL 碼值為 97
//故 strlen 會以此地址為起始地址向后尋找 '\0'
//但個人理解認位: 97 是一個沒有初始化的指針(地址),即野指針
//故這里會報錯
printf("%d\n", strlen(arr[1]));
//arr[1] 表數組第二個元素,即字符 'b' ,其 ASCLL 碼值為 98
//strlen 會以此地址會起始地址向后尋找 '\0'
//但個人理解認位:98 是一個沒有初始化的指針(地址),即野指針
//故這里會報錯
printf("%d\n", strlen(&arr));
//&arr 表取出整個數組的地址,但觀察 strlen 函數的聲明可以發現
//strlen 的函數參數是一個 char* 類型的指針
//即我們傳參傳進去的是一個數組指針,當 strlen 接收的時候,會將其強轉為字符指針
//故 strlen 會以數組首元素地址為起始地址,向后尋找 '\0'
//因為數組包含 '\0' ,故 strlen 的返回值為 6
printf("%d\n", strlen(&arr + 1));
//&arr+1 表取出整個數組的地址并向后跳躍一個數組類型大小
//即指向 '\0' 后一塊數組類型的空間
//strlen 會以此地址為起始地址向后尋找 '\0'
//但我們無法確定 '\0' 的具體位置,所以 strlen 會返回一個隨機值
printf("%d\n", strlen(&arr[0] + 1));
//&arr[0]+1 表取出數組首元素地址并向后跳躍一個 char 類型的大小
//即指向了數組第二個元素的地址
//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二維數組
#include <stdio.h>
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
//sizeof 內部放置的是數組名,故計算整個數組的大小
//即大小為 4(int類型)*12(元素個數)=48
printf("%d\n", sizeof(a[0][0]));
//sizeof 內部沒有單獨放置數組名,a[0][p] 表數組首元素
//故 sizeof 的計算值為 4(int類型)
printf("%d\n", sizeof(a[0]));
//sizeof 內部放置的看似不是單獨的數組名,但 a[0] 表數組的第一個元素
//此元素也是一個數組
//故 sizeof 計算的大小為 4(int類型)*4(元素個數)=16
printf("%d\n", sizeof(a[0] + 1));
//sizeof 內部放置的不是單獨的數組名,a[0] 表二維數組的第一個元素,即拿到了一個數組
//a[0]+1 表二維數組的第一個數組元素的地址并向后跳躍一個 int 類型的大小
//故 sizeof 計算的地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(*(a[0] + 1)));
//*(a[0]+1) 表對二維數組的第一個數組元素的地址并向后跳躍一個 int 類型的大小的解引用
//即找到了二維數組中的某一個元素
//故 sizeof 計算的大小為 4(int類型)
printf("%d\n", sizeof(a + 1));
//sizeof 內部沒有單獨放置數組名,a+1 表二維數組的首元素地址并向后跳躍一個一維數組類型的大小
//即指向了二維數組的第二個數組元素的地址
//故 sizeof 計算的地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(*(a + 1)));
//*(a+1) 表對二維數組的首元素地址并向后跳躍一個一維數組類型的大小的解引用
//即得到了二維數組的第二個元素
//此元素為一個一維數組,故 sizeof 計算的大小為 4(int類型)*4(元素個數)=16
printf("%d\n", sizeof(&a[0] + 1));
//&a[0]+1 表二維數組的首元素取地址并向后跳躍一個一維數組的類型大小
//指向了二維數組的第二個元素
//故 sizeof 計算的地址(指針)的大小為 4 or 8
printf("%d\n", sizeof(*(&a[0] + 1)));
//*(&a[0]+1) 表對二維數組的首元素取地址并向后跳躍一個一維數組的類型大小的解引用
//即得到了二維數組的第二個元素
//此元素是一個一維數組,故 sizeof 計算的大小的 4(int類型)*4(元素個數)=16
printf("%d\n", sizeof(*a));
//sizeof 內部沒有單獨放置數組名,*a 表對二維數組首元素地址解引用
//得到一個一維數組
//故 sizeof 計算的大小為 4(int類型)*4(元素個數)=16
printf("%d\n", sizeof(a[3]));
//a[3] 表二維數組的第三個元素
//需要說明的是,sizeof 只對類型感興趣
//也就是說,二維數組雖然不存在第三個元素,但它的類型依舊是二維數組
//故 sizeof 計算的是 4(int類型)*4(元素個數)=16
return 0;
}
原文鏈接:https://blog.csdn.net/weixin_59913110/article/details/125574395
相關推薦
- 2022-12-11 React組件的使用詳細講解_React
- 2022-07-15 Android拖拽助手ViewDragHelper的創建與使用實例_Android
- 2022-08-10 C#對WPF數據綁定的菜單插入Seperator分隔_C#教程
- 2022-07-06 Python?Pyecharts繪制桑基圖分析用戶行為路徑_python
- 2022-11-30 React18?中的?Suspense?API使用實例詳解_React
- 2022-11-05 Android?Jetpack組件中LifeCycle作用詳細介紹_Android
- 2023-05-17 一文速學Python+Pyecharts繪制樹形圖_python
- 2022-07-03 Python基礎教程之錯誤和異常的處理方法_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支