3

我有一个接收char *参数的函数:

Foo::Foo (char * arg0) {
    ....
}

在原始示例中, achar[]用于传递此值...

char bar[] = "Bar";
Instance.foo (bar);

...效果很好。

但是,我发现我可以传递一个字符串文字,转换为 a char *,而编译器不会发出任何警告。

Instance.Foo ((char *) "Bar");

但是,从我的阅读来看,似乎应该避免 - 指向的内存值可能会改变。

上述陈述是真的(“应该避免”)还是在这种情况下合适?


编辑 - 进一步的研究发现这篇文章很好地解决了我的问题......

4

2 回答 2

10

是的,避免这种情况。现在,如果您的函数使用 a const char *,那么使用字符串文字调用它并没有错。

C++ 编译器char *仅出于向后兼容的原因支持字符串文字,写入字符串文字会导致未定义的行为。

当你这样做时,你正在做一些根本不同的事情(即用你可以自由修改char bar[] = "Bar";的值初始化一个由 4 个字符组成的数组),而不是你做的事情(你正在创建一个指向你可能无法修改的 4 字节字符串的非指针) )。{'B', 'a', 'r', '\0'}char bar* = "Bar";const

在我看来,您永远不应该将字符串文字直接转换为 a ,而是将其明确地char*放入 a const char*then (如果您正在与旧版 API 通信),并附上评论说您正在与有保证的旧版 API 交谈不要改变s。这样做的好处是您可以在升级 API 时在程序中搜索那些 s,或者您想找到涉及写入 a 的分段错误来自何处。const_cast<char*>constcharconst_castchar*

甚至可以将遗留 API 与在其中const char*执行此操作的版本一起包装const_cast

绝对最糟糕的情况是有一堆char*s 闲逛,其中一些是可写的,另一些来自字符串文字。

于 2012-10-31T01:10:08.597 回答
1

应该不惜一切代价避免这种情况,并且只有在您必须与损坏的遗留 API 交互并且只有在您查看了它们的源代码并确保它们没有写入字符串时才能这样做。

保持安全,并strcpy在传递字符串之前复制字符串。

究竟什么是恶?写入字符串文字是未定义的行为。

于 2012-10-31T01:08:53.973 回答