将无符号字符数组从unsigned char*转换为char*

3

需要将unsigned char*类型的数组安全地转换为char*类型。我是这样做的,这样做是否正确?

std::vector < unsigned char > arr;
char *imgData = (char*) malloc( arr.size() );
for ( int i = 0; i < arr.size(); i++ ) imgData[ i ] = ( arr.at( i ) - 128 );

“安全转换”是什么意思? - ixSci
1个回答

5
不安全,特别是在C++中没有被定义行为。char可以被规定为有符号或无符号的,这取决于具体的实现。如果char是无符号的,在无符号char减去128后会截断一半的位。如果char是有符号的,则无法保证它是二进制补码表示,因此减去128将不会得到你想要的结果。 所以,试图进行的这种转换是不合理的。你将变量命名为imgData,因此似乎打算将该数据发送到某个图像API。而该API需要常规char。因此,你的目标似乎是将每个unsigned char转换为一个char,该char与原始的unsigned char具有完全相同的位模式。在这种情况下...只需将指针强制转换为static_cast(arr.data())。无论哪种方式,你都将引发未定义的行为。我宁愿用可能真正起作用的方法。此外,应注意到,C++14使得实现不使用二进制补码表示的char变得几乎不可能。这是因为需要通过可能带符号的char类型支持UTF-8。必须能够将char *强制转换为unsigned char*,并以保留所有有效UTF-8代码单元的位模式的方式转换回来。因此,强制转换仍然是最有可能实现你想要的功能的选项。

unsigned char* 转换为 char* 为什么会引发未定义行为? - ixSci
1
@ixSci:问题不在于转换,而在于访问。假设接收imgData的人实际上会将其作为char*读取或写入。如果他们这样做,那么就是未定义行为。如果他们在读取之前将其强制转换回unsigned char*,那么它就是明确定义的。 - Nicol Bolas
还有一个问题,虽然我理解通过char*写入unsigned char*数据可能会搞砸一切,但我不明白为什么你说从这个转换后的指针读取也是未定义行为。它不会读取从相应的无符号字符转换而来的定义良好的字符吗? - ixSci
@ixSci:什么是“相应的uchars”?char可以是有符号的,而许多无符号值没有相应的有符号值。请记住:C++不定义溢出语义等内容。如果您在unsigned char中有255,那么在char中它看起来像什么?谁知道呢;C++不会说。 - Nicol Bolas
但是 [conv.integral] 对于 "s -> u" 和反向转换都有规则。是的,它们没有被明确定义,而是由实现定义。但这并不意味着它们是未定义的,对吧?假设我们有一个程序,使用一个编译器编译,它写入、转换和读取值——我们不能有未定义的行为。我们无法说那里的确切值是什么,这是真的。但是我们保证它们将是一致的(如果实现是合理的,而不是试图破坏我们)。 - ixSci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接