从无签名转换为签名类型安全?

时间:2009-10-20 03:22:30

标签: c++ unsigned

例如,从unsigned char *转换为signed char *(或只是char *

是否安全?

8 个答案:

答案 0 :(得分:2)

访问是明确定义的,您可以通过指向与对象的动态类型对应的有符号或无符号类型的指针来访问对象(3.10 / 15)。

此外,signed char保证不会有任何陷阱值,因此无论原始signed char对象的值是什么,您都可以安全地读取unsigned char指针。< / p>

当然,您可以期望通过一个指针读取的值与您通过另一个指针读取的值不同。

编辑:关于sellibitze的评论,这就是3.9.1 / 1所说的。

  

char,签名字符和unsigned char占用相同数量的存储空间并具有相同的对齐要求(3.9);也就是说,它们具有相同的对象表示。对于字符类型,对象表示的所有位都参与值表示。对于无符号字符类型,值表示的所有可能位模式表示数字。

所以确实signed char似乎有陷阱值。很好听!

答案 1 :(得分:1)

转换应该是安全的,因为你所做的只是将一种类型的字符转换为另一种字符,它应该具有相同的大小。只需要知道在取消引用指针时代码所期望的数据类型,因为两种数据类型的数值范围不同。 (即如果指针指向的数字原来是无符号的,那么一旦指针被转换为有符号的字符*,它就可能变为负数而你取消引用它。)

答案 2 :(得分:1)

转换会更改类型,但不会影响位表示。从unsigned char转换为signed char不会改变该值,但它会影响值的含义。

以下是一个例子:

#include <stdio.h>
int main(int args, char** argv) {

  /* example 1 */
  unsigned char a_unsigned_char = 192;
  signed char b_signed_char = b_unsigned_char;
  printf("%d, %d\n", a_signed_char, a_unsigned_char); //192, -64

  /* example 2 */
  unsigned char b_unsigned_char = 32; 
  signed char a_signed_char = a_unsigned_char;
  printf("%d, %d\n", b_signed_char, b_unsigned_char); //32, 32

  return 0;
}

在第一个示例中,您有一个值为192的unsigned char或二进制的110000000。在转换为signed char之后,该值仍然是110000000,但这恰好是-64的2s-complement表示。有符号值以2s-补码表示形式存储。

在第二个例子中,我们的无符号初始值(32)小于128,因此它似乎不受强制转换的影响。二进制表示为00100000,仍然是32s的2s补码表示。

要从unsigned char“安全地”转换为signed char,请确保该值小于128。

答案 3 :(得分:0)

这取决于你将如何使用指针。您只是转换指针类型。

答案 4 :(得分:0)

您可以安全地将unsigned char*转换为char *,因为您正在调用的函数将期望来自char指针的行为,但是,如果您的char值超过127,那么您将得到一个结果不符合您的预期,因此请确保您的无符号数组中的内容对有符号数组有效。

答案 5 :(得分:0)

我看到它在某些方面出错了,从unsigned char转换为signed char。

其一,如果您将它用作数组的索引,该索引可能会变为负数。

其次,如果输入到switch语句,可能会导致负输入,这通常是交换机不期望的。

第三,它在算术右移上有不同的行为

int x = ...;
char c = 128
unsigned char u = 128

c >> x;

的结果不同
u >> x;

因为前者是符号扩展而后者不符号。

第四,签名字符会导致与无符号字符不同的点下溢。

这是一个常见的溢出检查,

(c + x > c)

可能会返回与

不同的结果
(u + x > u)

答案 6 :(得分:0)

如果您只处理ASCII数据,则安全。

答案 7 :(得分:0)

我很惊讶它尚未被提及:Boost numeric cast应该做的伎俩 - 当然只针对数据。

指针总是指针。通过将它们转换为不同的类型,您只需更改编译器解释指向的数据的方式。