[英]Question in number of bits in C programming
如果我做
int a = 3 ,則 3 將用 32 位二進制表示。
如果我做
char a = 3 ,則 3 將用 8 位二進制表示。
我的問題是在使用值進行初始化之前, 3代表多少位?
(換句話說,“3”在等號右邊有多少位)
int
具有 32 位是很常見的,但不能保證。 它也可以是 16 或 64。 或更高。
單個3
是int
類型的 integer 文字。
您可以使用sizeof
運算符檢查它。 它會給你以字節為單位的參數大小。 只需嘗試獲取int
、 a
和3
的大小。
#include <stdio.h>
int main()
{
int a = 3;
printf("%ld\n", sizeof(a)); // gives 4 bytes (32 bit) on my PC
printf("%ld\n", sizeof(int)); // gives 4 bytes (32 bit) on my PC
printf("%ld\n", sizeof(3)); // gives 4 bytes (32 bit) on my PC
return 0;
}
此外, 3
的類型為int
。 所以它的大小等於int
的大小。
int
類型的 object 的大小是實現定義的 該標准僅要求INT_MAX
不得小於+32767
,即2 ^ 15 - 1
如果在您的系統中, int
類型的 object 的大小等於 4,那么像3
這樣的 integer 常量將占用一個等於4
個字節的 memory 塊。
請注意,例如字符 integer 常量也具有int
類型。
所以在這兩個聲明中
char a = 3;
和
char a = '\3';
如果sizeof( int )
等於4
,則具有int
類型的常量3
和'\3'
占用4
個字節。
3
被稱為integer 常量,它的類型很像任何命名變量。 如果鍵入的數字可以放入int
int
否則,如果它不適合,編譯器會嘗試將它放入一個long
中,然后是long long
。
有各種相當復雜的規則來說明如何做到這一點,我不會在這里提及所有骯臟的細節——對此感興趣的人可以查看 C 標准 6.4.4.1 中的表格。 對於普通程序員來說,知道我們還可以通過添加U
后綴來強制 integer 常量無符號或通過添加L
后綴強制它變long
可能就足夠了。 即3U
或3L
或組合3UL
。 (小寫的u
和l
也可以。)
在現實世界的計算機上, int
總是 2 或 4 字節大。 long
是 4 或 8 字節大。 來自具有 4 字節int
和 8 字節long
的 64 位 Linux 計算機的示例:
#include <stdio.h>
int main (void)
{
printf("%zu\n", sizeof(int)); // 4
printf("%zu\n", sizeof(3)); // 4
printf("%zu\n", sizeof(3L)); // 8
printf("%zu\n", sizeof(2147483647)); // 4, fits int
printf("%zu\n", sizeof(2147483648)); // 8, doesnt fit
}
問題“3 代表多少位?” 實際上很棘手。 如果我們能找到3,那么我們就可以回答它。 所以問題是: 3 在哪里?
真正發生的是:
int a = 3;
是相同的:
int a;
a = 3;
編譯器確保變量a
將有 4 個字節的空間(它在編譯時執行此操作),然后它還會在程序中放置一條指令,當您運行程序時將數字 3 存儲在該空間中。
我們可以使用這個有用的在線工具來編譯程序並查看編譯器實際輸出的匯編/機器代碼: https://godbolt.org/z/a9Pohn
在這種情況下,我進入了程序:
int main() {
int a;
a = 3;
}
並用“x86-64 gcc 10.2”編譯它,沒有優化。 這是編譯后的代碼(匯編代碼和機器代碼):
main:
55 push rbp
48 89 e5 mov rbp,rsp
c7 45 fc 03 00 00 00 mov DWORD PTR [rbp-0x4],0x3
b8 00 00 00 00 mov eax,0x0
5d pop rbp
c3 ret
如果我們可以閱讀匯編,我們可以看到編譯器選擇插入到程序中來初始化變量a
的指令是mov DWORD PTR [rbp-0x4],0x3
。 在機器代碼中,它寫成c7 45 fc 03 00 00 00
。 指令是數字 3 的來源。
該指令長 7 個字節。 c7 45
告訴 CPU 這是什么類型的指令(“在堆棧幀中的特定 position 中放入特定數字”)。 fc
是堆棧幀中的 position。 03 00 00 00
是它放在那里的特定數字(以小端格式)。 這是源代碼中的數字 3。 所以在這種情況下,它占用了 4 個字節。
請注意,它並不總是相同的。 如果我們為 ARM CPU 而不是 x86-64 編譯,那么這些是相關指令
mov r3, #3
str r3, [fp, #-8]
不幸的是,godbolt 不會向我們顯示機器代碼,但我們可以在 ARM 手冊中查找 MOV # 指令,該指令告訴我們該指令長 4 個字節,而被移動的數字僅占用其中 2 個字節。 如果您使用的數字不適合 2 個字節,則其他位自動為零。 顯然它使用了不同的指令。
通常我們不會談論指令的大小,因為它們的變化比數據大小要大得多。 int a;
總是保留 4 個字節(如果您的系統的int
是 4 個字節),但是將特定位放入該空間的指令可以具有不同的大小。
即使在 x86-64 上,數字也可以占用不同數量的空間。 如果我確實return 0;
,編譯器將其轉換為xor eax, eax
( 31 c0
)。 該指令中根本沒有數字0
! ( 31 c0
是所有類型的指令,沒有數據)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.