调用函数时无条件地将所有unsigned char *转换为char *

unconditionally convert all unsigned char * to char * when calling a function

本文关键字:char unsigned 转换 函数 无条件 调用      更新时间:2023-10-16

我继承了一些代码,其中有许多类型为"unsigned char *"的变量,然而,当我必须调用一些常见的函数,如strstr,我必须做转换,如strstr((char*)x, "....")

不知道是否有编译器指令自动转换变量从unsigned char *char *时调用函数。我检查了代码,它本来可以达到目的的。

如果我不手动转换,例如,下面的小代码片段将生成编译器错误

int main(int argc, char *argv[]) {
    unsigned char *str = "hello world";
    if (strstr(str, "wor")) {
        printf("yesn");
    }
    return 0;
}

编译错误(命令行:g++ -std=c++11 te2a.cc)

te2a.cc:17:15: error: invalid conversion from ‘const char*’ to ‘uchar* {aka unsigned char*}’ [-fpermissive]
te2a.cc:18:23: error: call of overloaded ‘strstr(uchar*&, const char [4])’ is ambiguous
te2a.cc:18:23: note: candidates are:
In file included from te2a.cc:1:0:
/usr/include/string.h:321:14: note: char* strstr(char*, const char*) <near match>
/usr/include/string.h:321:14: note:   no known conversion for argument 1 from ‘uchar* {aka unsigned char*}’ to ‘char*’
/usr/include/string.h:323:22: note: const char* strstr(const char*, const char*) <near match>
/usr/include/string.h:323:22: note:   no known conversion for argument 1 from ‘uchar* {aka unsigned char*}’ to ‘const char*’

使用这种强制转换的程序行为是未定义的。这是因为指针类型是不相关的。

更详细地说:char可以签名或不签名,标准允许实现选择。因此,在一个系统上可能本质上是"无操作"的强制转换,在另一个系统上肯定不是"无操作"的强制转换。

同时,c++ 14之前的带符号char可以是1的补码(-127到+127)或2的补码(-128到127)。这并没有使这种类型的指针的转换变得特别简单。

一种补救方法是将代码重构为std::string

unsigned char*在逻辑上不是字符串,即使它以null结尾。编译器警告你,因为它不应该做出逻辑决定。

如果你知道它确实是一个兼容的字符串,你可以显式地强制转换它:

if (strstr((const char*)str, "wor")

这是不优雅的,你应该再想想为什么你的字符串是unsigned char*。大多数人使用unsigned char*只是为了将其与普通字符串区分开来,例如作为缓冲区。

也许你可以自己编写strstr的重载

strstr(unsigned char* s)
{
  strstr(reinterpret_cast<char*>(s));
}