关于C ++中的类型化的意见? [英] Opinions on type-punning in C++?

查看:98
本文介绍了关于C ++中的类型化的意见?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很好奇在C ++中类型冲突指针/数组的约定。这里是我现在使用的情况:


通过将一个二进制数据块计算为32位校验和,位整数(我们知道它的总长度是4的倍数),然后对所有值求和并忽略溢出。

我希望这样的函数看起来像这样:

  uint32_t compute_checksum(const char * data,size_t size)
{
const uint32_t * udata = / * ??? * /;
uint32_t checksum = 0;
for(size_t i = 0; i!= size / 4; ++ i)
checksum + = udata [i];
return udata;
}



现在我的问题是,你认为最好的将数据转换为 udata



  udata =(const uint32_t *)data 
  udata = reinterpret_cast< const uint32_t *>(data)

C ++在任意指针类型之间使用中间 void *

  udata = static_cast< const uint32_t *>(static_cast< const void *>(data))

透过工会投放?


b $ b

  union {
const uint32_t * udata;
const char * cdata;
};
cdata = data;
//现在使用udata

我完全意识到这不会是100%解决方案,但我只希望使用它在一小组平台上,我知道它的工作原理(即未对齐的内存访问和编译器假设指针别名)。

解决方案

就C ++标准而言,,还是将 const char * data 转换为 const uint3_t * $ c> static_cast 或 reinterpret_cast 打破严格别名规则(请参阅了解严格别名)。



通过联合体(如litb的 my_reint)进行强制转换)可能是最好的解决方案,虽然它在技术上违反了如果你通过一个成员写入联合并通过另一个读取它的规则,它导致未定义的行为。然而,实际上所有编译器都支持这一点,并且它产生预期的结果。如果您绝对希望符合标准100%,请使用位移位方法。否则,我建议通过联合投射,这可能会给你更好的性能。


I'm curious about conventions for type-punning pointers/arrays in C++. Here's the use case I have at the moment:

Compute a simple 32-bit checksum over a binary blob of data by treating it as an array of 32-bit integers (we know its total length is a multiple of 4), and then summing up all values and ignoring overflow.

I would expect such an function to look like this:

uint32_t compute_checksum(const char *data, size_t size)
{
    const uint32_t *udata = /* ??? */;
    uint32_t checksum = 0;
    for (size_t i = 0; i != size / 4; ++i)
        checksum += udata[i];
    return udata;
 }

Now the question I have is, what do you consider the "best" way to convert data to udata?

C-style cast?

udata = (const uint32_t *)data

C++ cast that assumes all pointers are convertible?

udata = reinterpret_cast<const uint32_t *>(data)

C++ cast that between arbitrary pointer types using intermediate void*?

udata = static_cast<const uint32_t *>(static_cast<const void *>(data))

Cast through a union?

union {
    const uint32_t *udata;
    const char *cdata;
};
cdata = data;
// now use udata

I fully realize that this will not be a 100% portable solution, but I am only expecting to use it on a small set of platforms where I know it works (namely unaligned memory accesses and compiler assumptions on pointer aliasing). What would you recommend?

解决方案

As far as the C++ standard is concerned, litb's answer is completely correct and the most portable. Casting const char *data to a const uint3_t *, whether it be via a C-style cast, static_cast, or reinterpret_cast, breaks the strict aliasing rules (see Understanding Strict Aliasing). If you compile with full optimization, there's a good chance the code will not to the right thing.

Casting through a union (such as litb's my_reint) is probably the best solution, although it does technically violate the rule that if you write to a union through one member and read it through another, it results in undefined behavior. However, practically all compilers support this, and it results in the the expected result. If you absolutely desire to conform to the standard 100%, go with the bit-shifting method. Otherwise, I'd recommend going with casting through a union, which is likely to give you better performance.

这篇关于关于C ++中的类型化的意见?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆