2010-10-31 87 views
5

從我所瞭解的'&'運算符開始,它返回內存中操作數的基地址。瞭解'&'運算符

讓我們想象一下以下情形(如我的機器上):

  • 的sizeof(INT)= 4個字節
  • 的sizeof(浮動)= 4個字節
  • 的sizeof(焦炭)= 1個字節

現在,如果我寫的東西是這樣的:

void main() { 
int i = 5411; 
int *ip = &i; 
char *c = &i; 

printf("%d",*ip); 
printf("%c",*c); 
} 

第一個printf()應該給我5411.說到第二個printf(),我的基地址包含10101001(char類型指針的高階8位= 1字節)。 因此* c應該給我169,當它轉換成%c時是一個無效的字符。

但編譯器給我'#'或其他有效的輸出。爲什麼這樣?任何投入?

編輯(從作者的評論答案的一個拍攝):

這只是一個虛擬的情況下,因爲我是從實際的機器了。
實際情況是我= 5411

+0

在任何情況下,如果您嘗試「打印」「字符」,它將顯示爲字符,而不是相應的整數代碼。 – 2010-10-31 20:20:56

+0

可能與使用字符編碼有關,我猜想。 – 2010-10-31 20:21:48

+0

是的,我也同意這一點。但是必須有一個從上一次printf()獲得'#'值的理由。這不是垃圾值。 – 2010-10-31 20:23:03

回答

24

您似乎很難理解整數如何存儲在內存中。以5411爲例。

5411 = 1010100100011 

這個數13的二進制數有然而,由於int是32位的,它必須是墊32個位數

5411 = 00000000 00000000 00010101 00100011 

在一個小端機(X86,默認情況下ARM),所述至少顯著字節被存儲在前面,所以在存儲器中:

00100011 00010101 00000000 00000000 
^ 
c   c + 1  c + 2  c + 3 
ip 

因此,*c應返回00100011即35('#')。

+0

嘿,非常感謝!這正是我所期待的:-) – 2010-10-31 20:45:22

+0

'5411'從哪裏來? OP的代碼清楚地用'1154'初始化'i'。 – AnT 2010-10-31 20:48:16

+0

@AndreyT:查看OP對其他答案的評論。 – kennytm 2010-10-31 20:48:47

5

ASCII只定義字符可達127除此之外,你真正想要做的是打印在*c數字對應的值,這也是採用%d完成。 ..

printf("%d",*c); 

...如你預期應顯示的數量。

+0

這只是一個虛擬的案例,因爲我遠離了實際的機器。實際情況是i = 5411.%c給出'#',%d給出35(而不是169) – 2010-10-31 20:26:23

+0

@Guarav:ASCII仍然只定義了127個字符,而你真正想要的是打印數字,所以打印號碼,而不是字符。 – 2010-10-31 20:27:41

+2

@Gaurav - 你爲什麼期待169?在一個小端機器上,它應該是35.在一個大端機器上,對於「擴展ASCII」應該是0. – 2010-10-31 20:32:08

1

* c的地址是i的地址,因爲您已將c分配給& i。然後它將採用最高或最低(取決於末端)並打印該字符。

+0

i = 5411的情況是打印'#'作爲字符。 35(10101001)的ASCII,它既不是高8位也不低8位。 – 2010-10-31 20:31:25

+0

@Gaurav - 35二進制是00100011 – 2010-10-31 20:35:09

+0

同意。 * c將不會被截斷,因爲字符指針足夠大以保存內存位置的整個值。 – 2010-10-31 20:35:18

1

只是爲了學習一些有關你的整數的編碼,你應該嘗試一下,做

printf("0x%X, %X|%X|%X|%X\n", 
    i, 
    i & 0xFF, 
    (i >> 8) & 0xFF 
    (i >> 16) & 0xFF 
    (i >> 24) & 0xFF 
); 

的然後做同樣的c[0]c[1]等和其他格式字符串作爲%c

3

首先,你的程序不合格。 C和C++都不允許初始化帶有int *值的char *指針。您需要在初始化指針c時進行顯式強制轉換。

其次,原始整數i的哪個字節 - 高階或低階 - 駐留在其「基址」是實現定義的。有小端架構,其中較低階但將通過*c(在8位char機器上具有值130,而不是114)看到。並且有大端架構,其中較高階但是將通過*c(在8位char機器上的0)被看到。因此,您應該期望代碼爲130的字符或代碼爲0的字符使用%c格式說明符打印。

第三,在典型的實現中,通常沒有「無效字符代碼」之類的東西。對於任何代碼,通常都會以某種方式打印。我沒有看到你是如何設法獲得#作爲你的代碼的輸出。這是你正在運行的真實代碼嗎?

+0

嗨安德烈。 1->代碼正在編譯。我應該關心顯式投射嗎? ... 2->是的,我沒有意識到這一點,KennyTM回答了...... 3->我提到,這是一個虛擬代碼 – 2010-10-31 20:54:58

+1

@Gaurav Kalra:編譯成什麼?你標記了你的問題[C]和[C++]。這段代碼不會被任何自尊的C++編譯器編譯爲C++。過度寬鬆的錯誤檢查的C編譯器可能會允許(帶有警告),但即使C代碼仍然是非法的,所以如果您關心編寫有效的C代碼,則需要執行強制轉換。 – AnT 2010-10-31 21:22:51