2011-06-15 184 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所需的存储空间取决于实现,可能不止一个字节。

为了节省内存,您可以使用(编译器特定)指令来请求数据结构的最佳打包,但导致的错误对齐的内存访问可能会导致性能问题。