如何将const char*转换为char*

20

请问有人可以告诉我如何将const char*转换为char*吗?

get_error_from_header(void *ptr, size_t size, size_t nmemb, void *data) {
    ErrorMsg *error = (ErrorMsg *)data;
    char* err = strstr((const char *)ptr,"550");
    //error  cannot convert const char** to char*
    if(err) {
        strncpy(error->data,(char*)ptr,LENGTH_ERROR_MESSAGE-1);
        error->data[LENGTH_ERROR_MESSAGE-1] = '\0';
        error->ret = true;
    }
    return size*nmemb;
}
6个回答

17

这里有几个问题我不理解。我看到标签是C++/CLI,但我下面所描述的应该与标准C++相同。

无法编译

您提供的代码无法编译;get_error_from_header没有指定返回类型。在我的实验中,我将返回类型设置为size_t

C++ strstr()的签名

标准C库中strstr()的签名是:

char *
strstr(const char *s1, const char *s2);

然而,在C++库中,strstr()函数的签名因重载而异,可能是以下之一:

const char * strstr ( const char * str1, const char * str2 );
      char * strstr (       char * str1, const char * str2 );

我会选择第一个重载,因为你不想修改字符串,只需要读取它。因此,你可以将你的代码更改为:

const char* err = strstr((const char *)ptr, "550");
if (err != NULL) {
    ...
}

另外,我假设您的评论指出了错误:

//error  cannot convert const char** to char*

有一个拼写错误:看不到 const char **

无需分配给 err

如先前的答案所指出的,如果 err 只用于检查NULL,则无需使用err来存储strstr的结果。因此,您可以使用:

if (strstr((const char *)ptr, "550") != NULL) {
    ...
}

鼓励使用reinterpret_cast<>

正如另一个回答所指出的,你应该使用reinterpret_cast<>而不是C风格的转换:

if (strstr(reinterpret_cast<const char *>(ptr), "550") != NULL) {
    ...
}

使用const_cast<>去除const

根据问题中的示例,我不认为这是必要的。但如果您有一个需要去除const的变量,您应该使用const_cast<>运算符。如下所示:

const char * p1;
char * p2;

p2 = const_cast<char *>(p1);

正如评论中所指出的那样,使用const_cast<>运算符的原因是为了使作者的意图清晰,并且便于搜索const_cast<>的用法;通常去除const是错误或设计缺陷的根源。


我认为"const char** to char*"只是打错了字。我同意,如果一个变量从未被使用,那么创建它就没有意义。所以,基本上我同意你的“不必要的const-ing”代码,只是我不清楚reinterpret_cast的好处在哪里。 - Matthew Flaschen
1
你引用了C语言中strtr()的签名,而不是C++。 - MSalters
使用const_cast的另一个原因是它更容易搜索。通过在代码中简单搜索“const_cast”关键字,您可以找到开发人员更改constness的所有位置。这很好,因为constness的更改通常是问题/错误的源头。 - Cătălin Pitiș
谢谢您提供的 p2 = const_cast<char *>(p1); 这正是我在寻找的。 - Katu
你提到了鼓励使用reinterpret_cast<>,你能帮忙理解为什么相对于const_cast<>这是一个不好的选择吗? - Krishna Oza
显示剩余3条评论

9

在该函数的其余部分中似乎没有使用err,那么为什么要创建它呢?

if (NULL != strstr((const char *)ptr, "550"))
{

如果你确实需要它,那么你真的需要修改它所指向的内容吗?如果不需要,那么也将其声明为const

const char* err = strstr((const char *)ptr, "550");

最后,由于强制类型转换可能会造成问题,因此最好使用特定的现代风格的强制类型转换来执行所需操作。在这种情况下:

if (NULL != strstr(reinterpret_cast<const char *>(ptr), "550"))
{

8

你不能只是这样做吗:

char* err = strstr((char *)ptr,"550");

错误是因为如果你将const char*传递给strstr,你会得到一个输出(因为有重载)。

取决于他最终想用它做什么(目前除了检查是否为空之外什么都不做)。 - Matthew Flaschen

5

//尝试使用下面的代码:

const char* mstr="";
char* str=const_cast<char*>(mstr);

0

根据我的深入研究,我发现许多论坛没有直接的解决方案或参考答案,于是我深入研究了GCC在线文档,对他们的编译器文档进行了简要阅读,以下是我能提供的内容。

在GNU C中,带有限定符的数组指针与其他带有限定符的类型的指针类似。例如,类型为int ()[5]的值可用于初始化类型为const int ()[5]的变量。然而,在ISO C中,这些类型不兼容,因为const限定符正式附加到数组的元素类型而不是数组本身。

如果我们采取这种方式,可能更容易理解这个描述。

extern void
transpose (int N, int M, double out[M][N], const double in[N][M]);
double x[3][2];
double y[2][3];
…
transpose(3, 2, y, x);

从上面的观察可以得出,如果你有一个

s1=createStudent(s1, 123, "Poli");
s2=createStudent(s2, 456, "Rola);

对于"Poli"和"Rola"的const char[5],它们与char a[]有关联。但是,由于每个元素都有限定符,而不是整个数组作为const,因此严格禁止这样做。


0

你传入的 void* 指针变量 ptr 是否是 const 型变量呢?也就是说,你是否能控制其所指内存区域?如果不能,那么在调用 strstr 函数时请将其转换为 char* 类型而非 const char*。如果是 const 型变量,那么你将得到一个 const char* 类型的返回值(该指针指向 ptr 所指字符串中的某个位置),然后你需要使用 strncpy 将其复制到另一个由你管理的字符串空间中。


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