重新解释与unsigned char *和char *之间的强制转换

时间:2009-08-04 20:25:13

标签: c++ templates casting

我想知道是否有必要在下面的函数中重新解释。 ITER_T可能是char *,unsigned char *,std :: vector< unsigned char>迭代器,或其他类似的东西。到目前为止它似乎没有受到伤害,但是转换是否会影响字节的复制方式?

template<class ITER_T>
char *copy_binary(
  unsigned char length,
  const ITER_T& begin)
{
  // alloc_storage() returns a char*
  unsigned char* stg = reinterpret_cast<unsigned char*>(alloc_storage(length));
  std::copy(begin, begin + length, stg);
  return reinterpret_cast<char*>(stg);
}

4 个答案:

答案 0 :(得分:6)

reinterpret_casts用于低级实现定义的强制转换。根据标准,reinterpret_casts可用于以下转换(C ++ 03 5.2.10):

  • 指向整数类型的指针
  • 积分类型指针
  • 指向函数的指针可以转换为指向不同类型函数的指针
  • 指向对象的指针可以转换为指向不同类型对象的指针
  • 指向成员函数的指针或指向数据成员的指针可以转换为不同类型的函数或对象。这种指针转换的结果是未指定的,除了指针a转换回其原始类型。
  • 如果可以使用reinterpret_cast将指向类型A的指针显式转换为类型B,则可以将类型A的表达式转换为对类型B的引用。

也就是说,在你的情况下使用reinterpret_cast不是一个好的解决方案,因为标准没有指定转换为不同的类型,但是从char *转换为unsigned char *并返回在大多数机器上工作。

在您的情况下,我会考虑将static_cast定义为stg类型为char *,而不是使用template<class ITER_T> char *copy_binary( unsigned char length, const ITER_T& begin) { // alloc_storage() returns a char* char* stg = alloc_storage(length); std::copy(begin, begin + length, stg); return stg; }

{{1}}

答案 1 :(得分:1)

根据标准4.7(2),编写的代码按预期工作,但这仅适用于具有二进制补码表示的机器。

如果alloc_storage返回一个char *,并且'char'被签名,那么如果我正确理解了4.7(3),那么如果迭代器的值类型是unsigned并且你放弃了强制转换并传递了char,那么结果将是实现定义的*复制。

答案 2 :(得分:1)

简短的回答是肯定的,它可能会影响。

char unsigned char 是可转换类型(C ++标准0x n2800中的3.9.1),因此您可以将一个分配给另一个。 您根本不需要演员。

  

[3.9.1] ...一个字母,一个签名的字符和一个未签名的字符   char占用相同的存储空间   并具有相同的对齐方式   要求;也就是说,他们有    相同的对象表示


  

[4.7] ......

     

2 如果目的地类型是   无符号,结果值是   最小符号无符号整数   源整数(模2n,其中n   是用于的位数   代表无符号类型)。

     

[注意:   在二进制补码表示中,   这种转换是概念性的   位模式没有变化   (如果没有截断)。 - 注意   ]

     

3 如果目标类型已签名,    值不变 如果可以的话   以目的地类型表示   (和位域宽度);否则,   值是实现定义的。

因此,即使在最坏的情况下,您也会获得最佳(实现定义较少)的转换。无论如何,在大多数实现中,这不会改变位模式中的任何内容,如果查看生成的汇编程序,您甚至不会进行转换。

template<class ITER_T>
char *copy_binary( unsigned char length, const ITER_T& begin)
{
  char* stg = alloc_storage(length);
  std::copy(begin, begin + length, stg);
  return stg;
}

使用reinterpret_cast,你依赖于编译器:

  

[5.2.10.3]执行的映射   reinterpret_cast是   的 实现定义 即可。 [注意:它   可能会,也可能不会产生   表示不同于   原始价值。 - 后注]

注意:This是一个有趣的相关帖子。

答案 3 :(得分:0)

因此,如果我做对了,对无符号字符的强制转换是为了保证一个无符号的逐字节拷贝。但是你把它归还给了回归。该函数看起来有点狡猾,这样设置的上下文/原因究竟是什么?快速修复可能是用memcpy()替换所有这些(但是注释,不要在迭代器对象上使用它) - 否则只需删除多余的强制转换。