網站首頁 編程語言 正文
? ? 很多同學可能在學習數組時會有這個疑問,下標為什么不從1開始呢?從1開始不是更符合大家的日常習慣嗎?生活中我們通常說第1個,而不是第0個。的確,有些計算機語言如早期的Pascal語言,數組元素的下標是從1開始的。難道是C語言故意要與眾不同?要弄清楚這個問題,得先看一下計算機底層是怎樣處理數組元素的。我們先編寫了一個小程序,然后在visual studio中對其進行了反匯編。源程序和反匯編后的部分代碼如下:
源程序:
int arr[5];? //一個全局數組 int main() { ?? int i; ?? for (i =0;i < 5;i++) ????? arr[i] = 9; ?? return 0; }
反匯編后的部分代碼:
int i; | ||
for (i = 0; i < 5; i++) | ||
0101168E |
C7 45 F8 00 00 00 00 |
mov dword ptr [ebp-8], 0 |
01011695 |
EB 09 |
jmp 010116A0 |
01011697 |
8B 45 F8 |
mov eax, dword ptr [ebp-8] |
0101169A |
83 C0 01 |
add eax,1 |
0101169D |
89 45 F8 |
mov dword ptr [ebp-8],eax |
010116A0 |
83 7D F8 05 |
cmp dword ptr [ebp-8],5 |
010116A4 |
7D 10 |
jge 010116B6 |
arr[i] = 9; | ||
010116A6 |
8B 45 F8 |
mov eax,dword ptr [ebp-8] |
010116A9 |
C7 04 85 80 95 01 01 09 00 00 00 |
mov dword ptr [eax*4+01019580h], 9 |
010116B4 |
EB E1 |
jmp 01011697 |
return 0; | ||
010116B6 |
33 C0 |
xor eax,eax |
? ? 上表中除了程序源代碼,其它部分中,最左列是指令的地址,中間是機器碼,也就是機器最后執行的代碼,右列是對應的匯編語言代碼。可能初學者看不懂這些匯編代碼,沒有關系。我們重點看一下這一句:mov???dword ptr [eax*4 + 01019580h] , 9?它的功能就是arr[i] = 9,其中eax中存放著變量i的值,4表示每個元素占4個字節,01019580h是數組arr的首地址,為了確認,可以在監視窗口中鍵入arr或者&arr[0],我們可以看到它們的值等于0x01019580h,如下圖所示:
? ? 也就是說,在給第i個元素賦值時,先要計算它的地址,即:首地址+i*4,在這個例子中,首地址是01019580h,所以第0個元素存放在以01019580h 開始的四個字節中,第1個元素存放在以01019584h 開始的四個字節中,…,第4個元素存放在以01019590h 開始的四個字節中。計算出地址后,用mov指令將9傳遞到該地址開始的4個字節中存放。執行完for循環后,查看01019580h開始的內存情況,如下圖所示:
? ? 可以看到,以0x01019580h開始的連續20個字節中存放著5個9。
? ? 從上面看出,當數組元素下標從0開始時,每個元素的地址計算如下:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第0個元素地址:首地址 (首地址 + 0*4)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第1個元素地址:首地址 + 1*4
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第2個元素地址:首地址 + 2*4
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? …
? ? ? ? ? ? ? ? ? ? ? ? ? ? 第i個元素地址:首地址 + i*4
? ? 當數組元素下標從1開始時,每個元素的地址計算如下:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第1個元素地址:首地址
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第2個元素地址:首地址 +(2-1)*4
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第3個元素地址:首地址 +(3-1)*4
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? …
? ? ? ? ? ? ? ? ? ? ? ? ? ? 第i個元素地址:首地址 +(i-1)*4
? ? 很明顯,如果數組元素下標從1開始,每次計算地址時,需要多做一次減法操作。因此,為了提高效率,C語言數組元素下標從0開始。C語言的高效率就是體現在這些點點滴滴中的,需要在學習中慢慢體會!
原文鏈接:https://blog.csdn.net/bufanq/article/details/51330197
相關推薦
- 2022-04-12 C#實現六大設計原則之接口隔離原則_C#教程
- 2022-06-30 Python利用shutil模塊實現文件夾的復制刪除與裁剪_python
- 2022-05-08 利用Pandas讀取某列某行數據之loc和iloc用法總結_python
- 2022-09-11 Oracle學習筆記之視圖及索引的使用_oracle
- 2023-10-16 elementUI日期選擇器快速選擇 快捷選擇(本周、上周、本月、上月、季度等)
- 2022-08-26 如何利用python在剪貼板上讀取/寫入數據_python
- 2022-10-10 Android開發之permission動態權限獲取詳解_Android
- 2022-06-06 Docker鏡像構建之docker?commit的使用_docker
- 最近更新
-
- 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同步修改后的遠程分支