C ++中的两个'char*'铸件有什么区别

What is the difference between two 'char*' castings in c++

本文关键字:char 区别 什么 两个      更新时间:2023-10-16

>我确实有一个"C"函数

find_register(char *name)

从"C++"例程调用。第一个提示是

find_register("%ebx")

它会导致警告

deprecated conversion from string constant to 'char*'

好的,我将其更正为

find_register(string("%ebx").c_str())

这会导致错误消息

"invalid conversion from 'const char*' to 'char*'

最后

find_register((char*)string("%ebx").c_str())

被接受,没有错误消息和警告。

我的问题:1./错误消息的可能原因是更改"const char*"的可能性保持开放状态。没关系,但在第一种情况下,不太复杂的版本允许相同的操作,将字符串常量转换为"char *"是一种合法但已弃用的转换。背后还有什么更深层次的原因吗?

2./有没有简单的方法可以做我想做的事?(完美的(对于编译器)代码对于程序员来说几乎是不可读的)

原因在于C++语言的原始根源,回到与 C 语言一定程度的向后兼容性被认为很重要的时代。

在 C 语言中,字符串文字尽管不可修改,但具有类型 char [N] 。因此,它们可以隐式转换为 C 中的类型 char *。在C++字符串文本的类型为 const char[N] 。从形式上讲,const char[N]不能隐式转换为char *。但是由于上述C兼容性原因,原始C++规范(C++98)允许将字符串文字隐式转换为char *。此例外仅适用于直接字符串文本,作为对字符串文本提供的一种特殊处理形式。

但最终 C 兼容性的问题变得不重要,这种特殊处理在 C++03 中被弃用。所以,这就是编译器告诉你的。在您的find_register("%ebx")调用中,它同意将直接字符串文字转换为char *,但警告您此转换已被弃用。在C++11中,这种隐含的皈依被完全取缔。

在所有其他上下文(不是直接字符串文本)中,禁止将const char [N]const char *隐式转换为char *,并且一直被禁止。这就是为什么你的

find_register(string("%ebx").c_str())` 

变体没有编译的机会。

至于如何解决此限制...如果您确定find_register(char *name)不会尝试更改name指向的数据(并且您不能仅将find_register的参数类型更改为const char *name),则

find_register(const_cast<char *>("%ebx"))

是一个相当可接受的解决方案(附有适当的注释)。当然,如果find_register是一个修改函数,那么你必须做一些类似的事情。

char reg[] = "%ebx";
find_register(reg);

函数 find_register(char*) 的原型指示它可能会更改参数,因为它只是一个传递的指针。您没有提到您是否拥有该函数的源代码,所以我假设您没有,否则最好更改该函数以接受char const *,前提是它不会更改内容。

否则只需传递一个可修改的数组:

char arg[] = "%ebx";
find_register(arg);

写:

find_register((char*)string("%ebx").c_str())

很危险,如果函数确实修改了字符串怎么办,例如 strtok ?但是,如果您坚持至少尝试使用C++样式的铸造而不是C转换(在这种情况下find_register(const_cast<char*>("%ebx")))。

旁注:就我个人而言,我发现在可能的情况下避免使用 C 方式放置 const 更容易阅读。因此,当指针恒定时,与其写const char *char const *char * const,即 const 总是向左走 - 它更一致。

如果你将字符串文字传递给find_register(char *name),那么函数原型应该是find_register(const char *name)的,因为字符串文字是不可修改的。

通过这种转换,C++会很乐意让你搬起石头砸自己的脚并尝试修改name,这给了我一个分段错误,如以下代码所示:

void modifyIllegally(char* name) {
    name[0]='d';
}
int main() {
    modifyIllegally("abc");
}

编辑:如果您不控制 C 程序的 API 并且确定它不会更改char*,则可以使用编译器标志禁用此警告。对于 gcc,标志是 -Wno-write-strings .