2008-12-31 61 views
1

鑑於這一領域:將一個char鑄造成一個未簽名的短:在幕後發生了什麼?

char lookup_ext[8192] = {0}; // Gets filled later 

而且這樣的說法:

unsigned short *slt = (unsigned short*) lookup_ext; 

幕後會發生什麼? lookup_ext返回67 = 0100 0011(C),lookup_ext [1670]返回78 = 0100 1110(N)並且lookup_ext返回68 = 0100 0100(D);返回7800。但是slt [1670]返回18273 = 0100 0111 0110 0001.

我試圖將此端口移植到C#中,所以除了一個簡單的方法外,我還想知道這裏真正發生了什麼。自從我定期使用C++以來,已經有段時間了。

謝謝!

回答

6

你展現不投一個char unsigned short類型的聲明,它蒙上了指針爲char到指針無符號短。這意味着指向數據的通常算術轉換不會發生,並且通過slt變量訪問時,底層char數據將被解釋爲無符號短路。

請注意,sizeof(unsigned short)不可能是1,因此slt[1670]不一定對應於lookup_ext[1670]。更有可能 - 如果說例如sizeof(unsigned short)是兩個 - 以對應於lookup_ext[3340]lookup_ext[3341]

你知道爲什麼原來的代碼使用這個別名?如果沒有必要,可能值得嘗試使C++代碼更清晰並在移植之前驗證行爲是否保持不變。

+0

在32位機器上的無符號短16位,而字符是8位 – Calyth 2009-01-08 19:45:11

+2

通常,但它們不一定是。例如,字符和無符號短褲都可以是32位。 – 2009-01-10 18:02:13

2

如果我理解正確,類型轉換將8192尺寸的字符數組轉換成一半大小的是短int數組,這是4096

所以我不明白你是什麼樣的比較在你的問題。 slt [1670]應該對應於lookup_ext [1670 * 2]和lookup_ext [1670 * 2 + 1]。

+0

對。這解決了一切!謝謝。 – 2008-12-31 09:55:42

0

當你做 「無符號短SLT =(無符號短)lookup_ext;」 無。大小等於(無符號短)的字節從lookup_ext給出的位置拾取,並存儲在由slt指向的位置。由於unsigned short爲2個字節,因此lookup_ext的前兩個字節將存儲在由slt給定的位置。

+0

這是不正確的。見8.5.1 [dcl.init.aggr]。如果一個`initializer-list`比數組的長度短,那麼數組的其餘部分將被初始化值,因此將爲零,而不是垃圾。 – 2008-12-31 09:54:27

1

那麼,這個語句

char lookup_ext[8192] = {0}; // Gets filled later 

創建一個數組在本地或非本地,這取決於其中發生定義。像這樣初始化它,用一個聚合初始化器將它的所有元素初始化爲零(第一個顯式地,其餘的隱式地)。所以我想知道爲什麼你的程序輸出非零值。除非填充發生在閱讀之前,否則這是有道理的。

unsigned short *slt = (unsigned short*) lookup_ext; 

當您從該指針的目標讀取數據時,會將構成數組的字節解釋爲無符號短對象。嚴格地說,以上是未定義的行爲,因爲您不能確定該數組是否適合對齊,並且您將從指向未指向原始指向類型的類型的指針(無符號字符< - > unsigned short)中讀取數據。在C++中,從其他一些pod(普通的舊數據,也就是C中可能存在的所有結構和簡單類型(例如簡稱))中讀取值的唯一便攜方法是使用庫函數memcpymemmove

所以,如果你讀過*slt,你會解釋第一sizeof(*slt)字節數組,並嘗試它讀成無符號短(這就是所謂的type pun)。