2011-06-15 72 views
2

我將應用程序從32位移植到64位。
它是C風格的編碼(遺留產品),雖然它是C++。我有一個問題,即使用聯合和結構的組合來存儲值。這裏使用了一個名爲「Any」的自定義數據類型,它應該保存任何基本數據類型的數據。 Any的實現如下:指針轉換爲64位環境中的長移植問題

typedef struct typedvalue 
{ 
long data; // to hold all other types of 4 bytes or less 
short id; // this tells what type "data" is holding 
short sign; // this differentiates the double value from the rest 
}typedvalue; 

typedef union Any 
{ 
double any_any; 
double any_double; // to hold double value 
typedvalue any_typedvalue; 
}Any; 

該聯合的大小爲8個字節。他們使用了union,所以在給定的時間只有一個值,他們使用struct來區分類型。您可以在任何給定時間存儲double,long,string,char,float和int值。那是這個想法。 如果它是一個double值,則該值存儲在any_double中。如果它的任何其他類型,則它存儲在「數據」中,並且該值的類型存儲在「ID」中。 「符號」會告訴如果值「任何」持有雙重或其他類型。 any_any在代碼中用於寬泛地複製地址空間中的值,而不考慮類型。 (這是我們最大的問題,因爲我們不知道在給定的時間它會保持什麼!)

如果它的一個字符串或指針「任何」是假設保存,它存儲在「數據」(這是鍵入long)。在64位,這是問題所在。指針是8個字節。所以我們需要將「long」改爲等效的8個字節(long long)。但是那樣會將聯合的大小增加到16個字節,「any_any」的自由使用會導致問題。 「any_any」的用法太多,你永遠不知道它可以容納什麼。

我已經嘗試了這些步驟,結果不成功:
1.在結構中將「長數據」更改爲「長長數據」,這將使聯合的大小爲16個字節。 - 這將不允許數據作爲「any_any」(8字節)傳遞。
2.將結構聲明爲聯合內的指針。並將struct中的「long data」更改爲「long long data」。 - 這裏遇到的問題是,因爲它的指針我們需要爲結構分配內存。自由使用「any_any」使我們難以分配內存。有時我們可能會覆蓋內存,從而抹去價值。
3.創建一個單獨的集合,該集合將保存「數據」(鍵值對)的值。 - 這是行不通的,因爲這個實現是應用程序的核心,集合會運行到數百萬的數據。

有人可以幫我嗎?

+0

所以你有一個64位平臺,其中'sizeof(long)!= 8'? – Alnitak 2011-06-15 09:00:52

+0

@Alnitak nope,這是在窗口和sizeof(長)= 4。我需要改變這很長的ñ這就是我的問題在於 – Reji 2011-06-15 09:28:58

回答

1

「有人能幫助我嗎」這聽起來像是一種絕望的呼喊,我完全理解它。

無論誰寫這段代碼都有絕對沒有尊重爲了將來打樣或便攜性,現在你付出了代價。

(讓這是一個教訓,任何人誰說,「但我們的平臺是32位!我們將永遠不會使用64位!」)

我知道你會說「,但它的代碼量太大「,但你更好關閉重寫產品。這次做得很好!

+1

現在,如果我們都可以就「正確」的普遍定義達成一致。 .. – msandiford 2011-06-15 09:31:14

1

無視這一事實,最初的設計是瘋了,你可以使用<stdint.h>(或即將<cstdint>獲得可預測的一點:

struct typedvalue 
{ 
    uint16_t id; 
    uint16_t sign; 
    uint32_t data; 
}; 

union any 
{ 
    char any_raw[8]; 
    double any_double 
    typedvalue any_typedvalue; 
}; 

你還是不能保證typedvalue將緊湊,因爲不存在非char成員沒有對齊的保證。您可以做出struct Foo { char x[8]; };和類型一語雙關,讓您暢行無阻,就像*(uint32_t*)(&Foo.x[0]),如果你一定要*(uint16_t*)(&Foo.x[4]),而這也將是極其醜陋。

如果你在C++ 0x,我肯定會在sizeof(typedvalue) == sizeof(double)的某個地方拋出一個靜態斷言。

+0

在前面的解決方案中,'data'不能包含64位指針,所以它應該是'uint64_t'。此外,原始訪問可以改爲'char any_raw [sizeof(typedvalue)]'來應對可能的包裝問題 – 2011-06-15 09:17:20

+0

好點。我不知何故認爲我們需要保留8字節結構。嗯,我真的不知道爲什麼你會想要這樣的嵌套結構......我想你可以把它放到一個單元中:'union {char any_raw [16]; double any_double; struct {/ *其他專業的東西* /}; };'。我猜long double和int128_t也是可能的常見類型,所以不妨一路走到128位。 – 2011-06-15 09:36:49

+0

現在所有數據都需要32個字節而不是8個。我可以看到爲什麼我們需要一個64位地址空間來處理所有這些! :-( – 2011-06-15 09:53:19

0

如果需要同時存儲一個8字節的指針「類型」字段,那麼你沒有選擇,只能使用至少9個字節,並且在64位的系統對準將可能墊出到16字節。

你的數據結構應該東西這樣的:

typedef struct { 
    union { 
     void *any_pointer; 
     double any_double; 
     long any_long; 
     int  any_int; 
    } any; 
    char  my_type; 
} any; 

如果使用的C++ 0x考慮使用strongly typed enumerationmy_type領域。在早期版本中,enum所需的存儲空間取決於實現,可能不止一個字節。

爲了節省內存,您可以使用(編譯器特定)指令來請求數據結構的最佳打包,但導致的錯誤對齊的內存訪問可能會導致性能問題。