2013-06-27 54 views
4

我已經記不清,很久以前,我做了這樣的事情在C次數:在C中重新解釋內存的正確方法是什麼?

struct foo f; 
struct foo* pf = &f; 
char* pc = (char*) pf; 
transmit(pc, sizeof(f)); 

或許:

char* buffer[1024]; 
receive(buffer, 1024); 
float values[256]; 
for(int ii = 0; ii < 256; ii++) { 
    float* pf = (float*)(buffer + ii*4); 
    values[ii] = *pf; 
} 

或許:

uint32_t ipAddress = ...; 
uint8_t* p = (uint8_t*)&ipAddress; 
uint8_t octets[4] = {p[0], p[1], p[2], p[3]}; 
printf("%d.%d.%d.%d\n", octets[0], octets[1], octets[2], octets[3]); 

我剛纔發現,通過轉換爲另一個指針類型來重新解釋這樣一段內存會調用未定義的行爲。然而,上述所有例子都是絕對必要的。什麼是正確的做他們的方式?

+1

我可能會對'union'關鍵字感興趣嗎? – Christoph

+0

就我個人而言,我認爲使用聯合是一種比類型轉換更糟糕的解決方案。編寫更多的代碼,創建更多奇怪的類型,而且你仍然需要在整個地方施放。 –

+0

@CarlNorum:如果你的目標類型不是'char',只需投射指針就會導致UB;有效的打字規則基本上使C成爲強類型語言,其中類型信息被綁定到存儲位置本身;然而,類型系統是非常不健全的,因爲編譯器會樂意嘗試通過錯誤類型的表達式來訪問內存,但實際上可能會假定這些不變量存在於更高的優化級別(例如,在「嚴格別名」情況下) – Christoph

回答

5

鑄造到char *(或unsigned char *或其typedef)是一種特殊情況,而不是會導致未定義的行爲。

從C屬,6.3.2.3指針,第7段:

當一個指向對象轉換爲一個指針指向一個字符類型,則結果點到最低尋址的字節物體。連續遞增的結果,直到對象的大小,產生指向對象剩餘字節的指針。

你的第一個&第三個例子被這種情況所覆蓋。第二個例子有點拗口,但可能適用於大多數系統。你真正應該做的是直接讀成values

float values[256]; 
receive(values, sizeof values); // assuming receive() takes a "void *" parameter 

或者是這樣的(爲了避免對齊問題):

char buffer[1024]; 
receive(buffer, sizeof buffer); 
float values[256]; 
for(int i = 0; i < 256; i++) 
{ 
    char *pf = (char *)&values[i]; 
    memcpy(pf, buffer + i * sizeof(float), sizeof(float)); 
} 

(請注意,我改變buffer是一個char陣列 - 我認爲這是你的問題中的一個錯字)。

+0

您能否提供鏈接?我的K&R C書沒有多說...但是它又不是ISO或ANSI C. – Mgetz

+2

當然:[C11(PDF鏈接)](http://www.open-std.org/jtc1/sc22/wg14 /www/docs/n1570.pdf)或[C99(PDF鏈接)](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf),您的選擇。 –

+0

我是C新手,只是想知道'char * pf =(char *)&float [i];'。你究竟在這裏鑄造'char *'? (我的編譯器在''float'之前抱怨'解析錯誤') – qwwqwwq

相關問題