我们如何使用强制转换来将字符掩盖成字符串?

时间:2012-01-27 21:42:19

标签: c++ c

我需要尽可能快地完成数百万次。假设我有两个包含几个短char数组的列表:

"a b ", "a c ", "a x ", etc...
" w z", " w y", " q b"

现在我想要从每个列表中形成一个组合。例如,"a b "" w z"将成为"awbz"

似乎最有效的方法是将它们存储为32位序列:

"a b " --> 0x00620061
" w z" --> 0x7A007700

现在OR他们一起得到

0x7A627761 --> "awbz"

我的第一个想法是使用联合,但我知道这在技术上会呈现未定义的行为...写入union变量的一部分,然后从union中读取不同的类型。

union {
  unsigned char[4] c;
  unsigned int i;
};

我的第二个想法是使用强制转换在int和char []之间切换。有没有办法安全地这样做?

3 个答案:

答案 0 :(得分:2)

好消息是,在C11中,读取工会成员而不是最后写入的工会成员并不是未定义的行为。脚注95至6.5.2.3说

  

如果用于读取union对象内容的成员与上次用于在对象中存储值的成员不同,则该值的对象表示的相应部分将被重新解释为对象表示形式。 6.2.6中描述的新类型(有时称为''punning''的过程)。这可能是陷阱表示。

坏消息是C11编译器仍然很少见。但是,大多数编译器都按预期运行,而gcc长期以来一直保证这种行为。除非有非常强烈的理由不这样做,否则我会使用联盟。

答案 1 :(得分:2)

在C ++中,始终允许向char*输入punning。所以你很幸运。

只需使用int32_t按照您的建议存储值。将按位OR的结果存储在变量中,并在其地址上使用reinterpret_cast

int32_t first = 0x00620061;
int32_t second = 0x7A007700;
int32_t combined = first | second;
std::string s(reinterpret_cast<const char*>(&combined), 4);

演示:http://ideone.com/1KGBl

答案 2 :(得分:0)

在某些C / C ++规范中是否为UB,现实是使用union可能会在几乎所有编译器中按预期工作,例如:

union Char4Int32
{ 
  unsigned char[4] c; 
  unsigned int32_t i; 
}; 

Char4Int32 first, second, combined;
strncpy(first.c, "a b ", 4); 
strncpy(second.c, " w z", 4); 
combined.i = first.i | second.i;
std::string s(combined.c, 4);