有没有一种很好的方法可以将unsigned char *转换为char *?

时间:2011-01-16 22:15:20

标签: c++ casting reinterpret-cast

那些日子我一直在阅读reinterpret_cast<>以及如何使用它(并在大多数情况下避免使用它)。

虽然我了解使用reinterpret_cast<>进行投射,比如说unsigned char*char*实现已定义(因此非便携式 em>)似乎没有其他办法让有效地将一个转换为另一个。

假设我使用处理unsigned char*的库来处理某些计算。 Internaly,我已经使用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 个答案:

答案 0 :(得分:6)

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

使用几乎所有瑕疵(包括关于{{1}}的有限保证)的语言支持效率的语言时,不要过分介绍低效率。

这将违背语言的精神,同时坚持这封信。

干杯&amp;第h

答案 1 :(得分: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是三种不同的类型,统称为窄字符   类型。 char,签名字符和unsigned char占用相同的字符   存储量并具有相同的对齐要求(3.11);   也就是说,它们具有相同的对象表示。对于狭窄   字符类型,对象表示的所有位都参与   价值表示。对于无符号窄字符类型,全部   值表示的可能位模式表示数字。   这些要求不适用于其他类型。在任何特定的   实现时,普通的char对象可以采用相同的值   作为签名字符或未签名字符;哪一个是   实现定义的。

答案 2 :(得分:1)

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

我只想补充一点:

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

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

答案 3 :(得分:1)

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