1

那些天我一直在阅读很多reinterpret_cast<>关于应该如何使用它的文章(并且在大多数情况下避免使用它)。

虽然我知道使用reinterpret_cast<>to cast from,say unsigned char*tochar*实现定义的(因此是不可移植的),但似乎没有其他方法可以有效地将一个转换为另一个。

假设我使用一个unsigned char*处理一些计算的库。在内部,我已经用它char*来存储我的数据(而且我无法更改它,因为如果我这样做会杀死小狗)。

我会做类似的事情:

char* mydata = getMyDataSomewhere();
size_t mydatalen = getMyDataLength();

// We use it here
// processData() takes a unsigned char*
void processData(reinterpret_cast<unsigned char*>(mydata), mydatalen);

// I could have done this:
void processData((unsigned char*)mydata, mydatalen);
// But it would have resulted in a similar call I guess ?

如果我希望我的代码具有高度可移植性,我似乎别无选择,只能先复制我的数据。就像是:

char* mydata = getMyDataSomewhere();
size_t mydatalen = getMyDataLength();
unsigned char* mydata_copy = new unsigned char[mydatalen];
for (size_t i = 0; i < mydatalen; ++i)
  mydata_copy[i] = static_cast<unsigned char>(mydata[i]);

void processData(mydata_copy, mydatalen);

当然,这是非常不理想的,我什至不确定它是否比第一个解决方案更便携。

所以问题是,在这种情况下你会怎么做才能拥有高度可移植的代码?

4

4 回答 4

6

便携是一个实践中的问题。因此,对于在andreinterpret_cast之间进行转换的特定用途,它是可移植的。但是我仍然会将这种用法包装在一对函数中,而不是直接在每个地方进行。char*unsigned char*reinterpret_cast

当使用一种几乎所有缺点(包括对reinterpret_cast.

这将违背语言的精神,同时遵守文字。

干杯&hth。

于 2011-01-16T22:19:35.443 回答
2

char 和 unsigned char 类型之间的区别仅仅是数据语义。这只会影响编译器如何对任一类型的数据元素执行算术运算。char 类型向编译器发出信号,高位的值将被解释为负数,因此编译器应该执行二进制补码运算。由于这是这两种类型之间的唯一区别,我无法想象reinterpret_cast <unsigned char*> (mydata)会产生与(unsigned char*) mydata. 此外,如果您只是通知编译器有关数据语义的更改,即从有符号算术切换到无符号算术,则没有理由复制数据。

编辑:虽然从实际的角度来看,上述内容是正确的,但我应该注意到 C++ 标准规定 char、unsigned char 和 sign char 是三种不同的数据类型。§ 3.9.1.1:

声明为字符 (char) 的对象应足够大以存储实现的基本字符集的任何成员。如果该集合中的字符存储在字符对象中,则该字符对象的整数值等于该字符的单个字符文字形式的值。char 对象是否可以保存负值是实现定义的。字符可以显式声明为无符号或有符号。普通字符、有符号字符和无符号字符是三种不同的类型,统称为窄字符类型。char、signed char 和 unsigned char 占用相同的存储量并具有相同的对齐要求(3.11);也就是说,它们具有相同的对象表示。对于窄字符类型,对象表示的所有位都参与值表示。对于无符号窄字符类型,值表示的所有可能的位模式都表示数字。这些要求不适用于其他类型。在任何特定实现中,普通 char 对象可以采用与带符号字符或无符号字符相同的值;哪一个是实现定义的。

于 2011-01-17T01:03:01.240 回答
1

和演员一起去,在实践中没问题。

我只想补充一点:

for (size_t i = 0; i < mydatalen; ++i)
  mydata_copy[i] = static_cast<unsigned char>(mydata[i]);

虽然不是未定义的行为,但可以在没有 2 补码算法的机器上更改字符串的内容。相反将是未定义的行为。

于 2011-01-17T01:21:27.097 回答
1

对于 C 兼容性,unsigned char*andchar*类型有额外的限制。基本原理是函数memcpy()必须工作,这限制了编译器的自由度。(unsigned char*) &foo必须仍然指向对象 foo。因此,在这种特定情况下不要担心。

于 2011-01-17T08:21:29.397 回答