【问题标题】:ANSI C: Pointers to strings literals [duplicate]ANSI C:指向字符串文字的指针[重复]
【发布时间】:2011-11-23 15:17:25
【问题描述】:

可能重复:
Are string literals const?

以下内容在 ANSI C 中有效吗?

#include <stdio.h>

/* This returns "Hans" if arg != 0, "Gretel" if arg == 0 */
char* foo(int arg)
{
    return arg ? "Hans" : "Gretel";
}

int main()
{
    char* p_ch;

    p_ch = foo(1);
    printf("%s\n", p_ch);
    p_ch = foo(0);
    printf("%s\n", p_ch);

    return 0;
}

代码在 GCC/Linux 下编译运行良好。

MinGW/Windows 说:

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

MS Visual C/C++ 2008 的代码很好。

  1. 我可以在初始化时将char* 变量分配给其他地方的文字字符串吗?
  2. 我读过字符串文字有static alocation 类。这是否意味着它们在定义它们的函数之外是不可见的?
  3. 从什么时候开始,从 const 类型到它们的非 const 类型的转换无效?

【问题讨论】:

  • 我会声明foo 会返回const char*。当编译为 C++ 时,代码变得无效。我还不足以作为一个标准的专家来准确地解释为什么......我本来希望 GCC 会给出一些警告(但即使是带有-Wall -Wextra 的 gcc 4.6 也不会)。
  • @Basile,因为 gcc 正在编译 C 代码。这在 C 中没有有问题。如果你用 g++ 编译它,那将是另一回事,但如果你尝试编译完全有效的 C 代码,gcc 显然不会认为这是一个问题。像“不能使用 new 的变量名,如果有一天你可能想用 C++ 编译器编译它”这样的警告会非常烦人:-)
  • @BasileStarynkevitch: gcc -Wwrite-strings 给出了适当的警告。这可能不是-Wextra 的一部分,因为C 库的某些部分可能依赖于这个特性;例如,strerror 的返回类型为 char*,但可以使用字符串字面量数组来实现。
  • 感谢您的所有回答。无论如何,既然字符串文字属于static 分配类,它们在技术上不应该从函数foo() 之外不可见吗?是的,我知道,静态变量只是一个伪装的全局变量,因此它们会一直存在到程序终止,而p_ch 仍然是一个有效的指针 - 但我可以依赖这种行为吗?

标签: c string-literals


【解决方案1】:

是的,这是有效的标准 C。但是,它只是有效的,因为字符串文字的类型为 char[] 以实现向后兼容性;为了安全起见,您真的应该从fooconst char* 的返回值。写入 foo 返回的任一字符串都会引发未定义的行为。

如果您的编译器对此有所抱怨,那么您可能不小心使用了 C++ 编译器。在 C++ 中,字符串文字的类型为 const char []。 (如果您将char* 更改为const char*,您的程序也会神奇地变成一个有效的C++ 程序。)

我可以在初始化时将char* 变量分配给其他地方的文字字符串吗?

你是说

char *p;
// do some other stuff
p = "literal";

?是的,这是可能的。

我读过字符串文字有静态分配类。这是否意味着它们在定义它们的函数之外是不可见的?

您混淆了静态分配和static 变量。您当然可以在另一个翻译单元中使用来自foo 的结果。

从什么时候开始,从 const 类型到非 const 类型的转换无效?

自 1989 年正式将 const 引入 C 时。您必须明确地将 const 强制关闭。

【讨论】:

    【解决方案2】:

    您从 MinGW/Windows 编译器收到的错误消息强烈表明您正在将此代码编译为 C++。在 C 语言中,字符串文字具有 char[N] 类型(与 C++ 中的 const char[N] 相反)。在 C 语言中,您不应收到此错误消息。尽管如此,即使在 C 中,字符串文字也是不可修改的,这意味着在指向字符串文字时坚持使用 const char * 指针是个好主意。

    您的问题 1 有点奇怪。字符串文字是 nameless 对象,这意味着初始化是直接使指针指向字符串文字的唯一方法。没有别的办法。稍后您可以将非常量指针复制到其他非常量指针,这没关系。请记住,不允许通过这些指针将任何内容写入字符串文字:字符串文字是不可修改的。

    你的问题 2 也没什么意义。 “可见性”是 name 的属性。字符串文字是 nameless 对象。它们在任何地方都不可见。它们不可见,因为它们没有名字。由于它们没有名称,因此“获取”字符串文字并保留它的唯一方法是在指针初始化期间将指针附加到它(如您的示例中所示)。可见性与它完全无关。字符串文字确实具有静态存储持续时间,这意味着它们“永远存在”:只要程序运行它们就存在。在您的示例中,字符串文字 "Hans""Gretel" 即使在 foo 退出后仍然存在,这意味着 foo 返回的指针仍然有效。

    您的问题 3 的答案是:从 const 指针到它们的非 const 对应物的隐式转换在 C 语言中从未存在过,即它一直是无效的。您必须使用显式强制转换才能执行此类转换。

    【讨论】:

      猜你喜欢
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 1970-01-01
      • 1970-01-01
      • 2013-02-16
      • 2010-09-27
      • 2015-05-19
      相关资源
      最近更新 更多