2013-05-22 47 views
0

我需要找到最符合標準的方式來獲取指針的地址並分別存儲其字節(例如,串行傳輸)。指針地址符合標準的轉換

我有兩個版本,第一個包含,我相信,未定義的行爲,第二個,它應該只包含根據C99定義的行爲。但是我的工具告訴我,我還有第二個未定義的行爲。是否有人可以確認它,並且指出一個解決方案,如果可能,既沒有未定義的行爲,也沒有實現定義的行爲?

編輯:我改變了類型從intunsigned long找到一個非實現相關的解決方案,以幫助。我也刪除了「16位寬指針」。

unsigned long a[2]; 
unsigned char b0, b1, b2, b3; 

int main1() { 
    unsigned long l = (unsigned long) &(a[0]); 
    b0 = (l >> 24) & 0xFF; 
    b1 = (l >> 16) & 0xFF; 
    b2 = (l >> 8) & 0xFF; 
    b3 = l & 0xFF; 
    return 0; 
} 


typedef union { unsigned long* p; char c[sizeof(unsigned long *)]; } u; 

int main2() { 
    u x; 
    x.p = a; 
    b0 = x.c[3]; 
    b1 = x.c[2]; 
    b2 = x.c[1]; 
    b3 = x.c[0]; 
    return 0; 
} 

編輯2:加入參考關於這些程序C99標準的一部分:

任何指針類型可以被轉換爲整數類型。除了以前指定的以外, 結果是實現定義的。如果結果不能用整數類型表示,則 的行爲未定義。結果不需要在任何整數 類型的值的範圍內。

這是否意味着不可能在不依賴某些實現定義的行爲的情況下讀取數組a的地址?還是有辦法規避它?

+2

您確定要發送的地址?無論如何,它們在其他主機或另一個地址空間上都不會有效。 –

+1

我不知道任何具有16位指針的C的實現,但假設你是正確的(一些小的嵌入式系統或其他東西?)main1()沒有錯。你顯然使用聯合或main2()的東西,但是你沒有向我們展示那些代碼,所以我們不能幫你。 –

+0

'int i =(int)&(a [0]);'因爲'sizeof(int)!= sizeof(void *)'在某些系統上con有問題 –

回答

2

對於指針,最好使用unsigned long(或unsigned long long)。除非有數據類型uintptr_t。 爲什麼unsigned?因爲移位操作僅適用於無符號整數。對於簽名的,它是平臺依賴的。

所以,你要轉移的地址(無論出於何種原因,如地址通常是以流程爲本地),你可以做如下所示:

/** 
* @param ptr Pointer to serialize 
* @param buf Destination buffer 
* @param be If 0 - little endian, 1 - big endian encoding 
*/ 
void ptr2buf(const void *ptr, void *buf, int be) 
{ 
    uintptr_t u = (uintptr_t)ptr; 
    unsigned char *d = buf; 

    if (be) 
    { 
     /* big endian */ 
     d += sizeof(t) - 1; 

     for (i = 0; i < sizeof(t); ++i) 
     { 
      *d-- = u & 0xFF; 
      u >>= 8; 
     } 
    } 
    else 
    { 
     /* little endian */ 

     for (i = 0; i < sizeof(t); ++i) 
     { 
      *d++ = u & 0xFF; 
      u >>= 8; 
     } 
    } 
} 
+0

好的,如果我的工具告訴我所有三個程序(我的版本和你的)都有未定義的行爲,那麼我的工具只接受C的一個子集?行'* d-- = u&0xFF'是否包含未定義的行爲?或者只是實現定義的行爲?如果是這樣,是否有辦法避免它? – anol

+0

此代碼適用於所有機器。不,你指出的線是100%正確和合規的。如果你有一些工具告訴你,否則它是毫無價值的。 –

+0

只是爲了澄清我能從標準中得到什麼:'u&0xFF'包含一個指針類型('u')和一個按位AND運算符。然後將指針類型轉換爲整數類型,根據C99標準中的6.3.2.3.6項「結果是實現定義的」,然後對轉換結果執行按位運算。 換句話說,我相信如果不依賴至少一些實現定義的行爲,這意味着您的解決方案(也可能是我的解決方案)都符合標準,所以無法執行此轉換。 – anol