2013-10-12 54 views
0

我對C中的指針進行了一些回顧,而且我遇到了一些我遇到的代碼時感到困惑。我是在做qeeksquiz.com/pointers測驗複習,而我整個這一段代碼來:關於機器相關指針值的困惑

#include<stdio.h> 
int main() 
{ 
    int a; 
    char *x; 
    x = (char *) &a; 
    a = 512; 
    x[0] = 1; 
    x[1] = 2; 
    printf("%d\n",a); 
    return 0; 
} 

,當我遇到x = (char *) &a來到我有點糊塗了。我知道x是一個指針,它包含a的地址,但當我們指定x[0] = 1x[1] = 2;時,答案在打印時爲513.答案說明它如何依賴於我們正在使用的機器以及小端機器改變它如何讀取二進制文件。我完全困惑於我們如何從512到513.我猜這是因爲x [0] = 1,但我不是100%確定。有人可以幫忙解釋一下嗎?如果我們分配了x[0] = 2,那麼變化的值是多少?

感謝您的幫助!

+0

INT存儲爲一個字節序列。這裏只有2個字節被初始化:然後將值計算爲x [0] + 256 * x [1] = 1 + 256 * 2 = 513.如果它是一個不同的endian機器,那麼(假設int使用2個字節,這並不總是正確的),這可能是另一種方式:x [1] + 256 * x [0] = 2 + 256 = 258。 – Ashalynd

+0

你從哪裏獲得256乘以x [1]? – user1871869

+0

256是2 ** 8,而8是一個字節中的位數。 – Ashalynd

回答

2

爲x是字符指針,就意味着X [0]和X [1]是參照單個字節的數據,所以在存儲你有像這樣的數據:

1 2 

但是,輸出過程中你試圖引用與16/32位相同的數據,所以我們沒有2個單字節,而是1個字,它在內存中存儲爲0x01 0x02,對於小端,這意味着我們應該交換它們,所以我們得到編號0x201 ,這是十進制表示法中的513

對於大端序列它將是0x102它是十進制的258

+0

它不依賴於'sizeof(int)'嗎? –

+0

只有16位「int」纔會有258個。對於32位'int',它將是0x01020000 – kotlomoy

+0

@kotlomoy你是對的 –

2

ASCII藝術!

    Little endian    Big endian 

       +----+----+----+----+  +----+----+----+----+ 
a = 0x200:  | 00 | 02 | 00 | 00 |  | 00 | 00 | 02 | 00 | 
       +----+----+----+----+  +----+----+----+----+ 

       +----+----+----+----+  +----+----+----+----+ 
x[0] = 1:  | 01 | 02 | 00 | 00 |  | 01 | 00 | 02 | 00 | 
       +----+----+----+----+  +----+----+----+----+ 

       +----+----+----+----+  +----+----+----+----+ 
x[1] = 2:  | 01 | 02 | 00 | 00 |  | 01 | 02 | 02 | 00 | 
       +----+----+----+----+  +----+----+----+----+ 

result:   1x1 + 2x256 = 513  1x16777216 + 1x65536 + 2x256 + 0x1 = big 
1

整數由一系列字節組成。但是在不同的系統中字節的順序是不同的。例如,請考慮編號134480385(二進制= 00001000000001000000001000000001)。在小端系統,它是(在左側用最低的地址)

00000001 00000010 00000100 00001000

但大端系統上,則字節存儲周圍的其他方式。 LEFT仍然是最低的地址。

00001000 00000100 00000010 00000001

當你把整數及演員地址爲char(字節)的指針,它指向整數的第一個字節(最低的地址)。向指針寫入1時,最低字節設置爲00000001.但是,char只有1個字節長,所以其他字節不變。然後,第二個字節被設置爲00000010

在您的例子,512小尾數是

00000000 00000010

大端是更棘手的,因爲結果取決於有多少字節在INT。它通常是4,但可能是2或更多。作爲2個字節的INT,512內存

00000010 00000000

,併爲4個字節的詮釋是

00000000 00000000 00000010 00000000

(它不小端無所謂,因爲多餘的字節都只是零)

1寫入第一個字節,2到第二個字節後,在內存中得到一個4字節的小端

00000001 00000010 00000000 00000000

4字節大端

00000001 00000010 00000010 00000000

注意,在第三個字節的位仍然存在。這是因爲我們只寫了前兩個字節。第三和第四個字節保持不變。

和2字節的大端

00000001 00000010

解讀2或4個字節的存儲器(忽略2字節的額外的零),爲小端號碼作爲一個正常的二進制數是

00000000000000000000001000000001 = 513

解讀4字節存儲器作爲大端數作爲一個正常的二進制數是

00000001000000100000001000000000 = 16908800

解讀2個字節的內存一樣大尾數號碼作爲一個正常的二進制數是

0000000100000010 = 258

我可能犯了一個錯誤在我的計算,但希望你的想法。這就是爲什麼在不同類型的指針之間進行轉換時需要小心。

0

正如其他人指出的,訣竅是瞭解如何在內存中表示整數和字符。我已經編寫了一些C++代碼,試圖向您展示這一點。將其粘貼到一個文件中,編譯&運行;然後更改main中的值並查看會發生什麼情況。下面的代碼:

#include <stdio.h> 

// print one byte as a binary number 
void print_binary(unsigned u) { 
    for (int i = 7; i >= 0; --i) 
     printf("%d", (u >> i) & 1); 
} 

// print a number's binary representation 
template <typename T> 
void print_int_binary(T i) { 
    char *cp = (char*)&i; 
    for (int i = 0; i < sizeof(T); ++i) { 
     print_binary(cp[i]); 
     printf(" "); 
    } 
    printf("\n"); 
} 

// show how the variable is represented in memory 
template <typename T> 
void print_var_binary(const char *name, T t) { 
    printf("%s is stored as %d bytes:\n", name, (int)sizeof(t)); 
    print_int_binary(t); 
} 

#define PRINT(a) print_var_binary(#a, a); 

int main() { 
    PRINT((int)513) 
    PRINT((char)2) 
} 

當我在我的(小端)計算機上運行它,它打印:

(int)513 is stored as 4 bytes: 
00000001 00000010 00000000 00000000 
(char)2 is stored as 1 bytes: 
00000010