簡體   English   中英

C編程中位數問題

[英]Question in number of bits in C programming

如果我做

int a = 3 ,則 3 將用 32 位二進制表示。

如果我做

char a = 3 ,則 3 將用 8 位二進制表示。

我的問題是在使用值進行初始化之前, 3代表多少位?

(換句話說,“3”在等號右邊有多少位)

int具有 32 位是很常見的,但不能保證。 它也可以是 16 或 64。 或更高。

單個3int類型的 integer 文字。

您可以使用sizeof運算符檢查它。 它會給你以字節為單位的參數大小。 只需嘗試獲取inta3的大小。

#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可能就足夠了。 3U3L或組合3UL (小寫的ul也可以。)

在現實世界的計算機上, 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
}

https://godbolt.org/z/3675zv

問題“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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM