2012-09-24 54 views
1

将铸件解决下面的警告是否安全,或者我可以简单地改变原型来返回u_char而不是?将铸造一个char/unsigned char是否安全?

警告:返回 'u_char [256]' 从与结果类型的函数 '的char *' 指针为整数类型的具有不同符号之间转换[-Wpointer-SIGN]

char * whatever(unsigned char *text) 
{ 
     static u_char retval[256]; 
     int pos = 0; 

     *retval = 0; 
     if (!text) 
       return retval; 

     for (; *text && (pos < 254); text++, pos++) { 
       if (*text < 32) { 
         retval[pos++] = '^'; 
         retval[pos] = *text + 64; 
       } else if (*text == 127) { 
         retval[pos++] = '^'; 
         retval[pos] = '?'; 
       } else 
         retval[pos] = *text; 
     } 

     retval[pos] = 0; 
     return retval; 
} 

我也可以接受其他可能性。

回答

2

当然你应该改变返回类型,如果你认为数据是无符号的。

一般来说,你的代码有点吓人,因为它似乎是根据ASCII值硬编码有关字符的假设。这不是我推荐做的事情,请看isprint()功能和朋友检查角色的便携方式。文本通常假定为const char *,而不是const unsigned char *

最后,当然返回一个指向static缓冲区的指针也会有点危险,代码不是线程安全的,并且如果多次调用完成,很难在外部跟踪返回值并实现它被随后的调用覆盖。

+0

我敢说每个人*都会假设文本是'const unsigned char *'。对于很多人来说,差异并不重要,只要手中的实现将'char'视为签名而不是无符号类型即可。 –

1

因为你的函数使用输入的unsigned char*,似乎有理由为它的输出返回unsigned char*,除非功能的预期目的部分是转换从unsigned charchar。如果这是目的的一部分,那么retval应该是一个char的数组,而不是数组u_char

unsigned char转换为char很可能是2补码实现(几乎所有这些)的无操作。但实际上并没有保证,即使是2的补码。对于大于CHAR_MAX(通常为127)的值,允许转换改变位模式或者甚至提高信号。在从unsigned char转换为char不是的实施方案中,没有任何操作(大约没有任何操作),从unsigned char*转换为char*是不安全的,因此警告。

所以实际上,这个警告告诉你需要决定(和记录)你的函数处理什么类型的字符。不要避免使用一个强制转换的决定。

0

有数百万行代码将char*unsigned char*视为可互换,而C标准并未要求它们可互换。是否“安全”取决于您所说的单词的含义......如果您认为您可能将代码移植到当前不存在的不兼容的兼容实现中,或者如果您订阅书面说,任何不符合C标准的东西都可能会擦掉硬盘。

但是,编写正确的类型安全代码要好得多,在这种情况下甚至不会出现问题。换句话说,不要避免演员因为它是“不安全的”,避免演员因为它是不好的编码练习。部分糟糕的是,任何演员都可以隐藏bug ...举个例子,假设你认为char*unsigned char*实际上是一些其他类型,比如intint* ......你刚刚阻止了编译器告诉你它。类型和类型安全性是通过在编译时尽早捕获错误来避免错误的强大工具。