【问题标题】:Why use the const char* form for a string为什么对字符串使用 const char* 形式
【发布时间】:2021-05-11 13:34:24
【问题描述】:

创建字符串有以下两种形式:

const char* pt1 = "Hello";
      char* pt2 = "Goodbye";

上面const有什么用?据我了解,这样做:

ptr = "Adios";

两者都适用,因为这会更改指针的地址,但尝试更改字符串中的字母对两者都将失败:

const char* pt1 = "Hello";

编译器错误:分配了只读位置

char* pt2 = "Goodbye";

运行时错误:段错误,正在尝试更改 .rodata

由于它们产生相同的结果——即错误——在定义字符串时使用const 有什么好处吗?

【问题讨论】:

  • Since they produce the same output compiler error: assignment of read-only location 绝对不同于 runtime error: seg fault, trying to change .rodata
  • 但是你想什么时候失败?当你编译你的程序,或者当你的客户购买了你的程序并且你发送了你的程序并且它出现了故障,所以你必须退款? compiler errorruntime error 之间有一个特定的区别 - 第一个很容易检测和修复。另一个是程序错误,可能会造成灾难性后果。
  • @samuelbrody1249 你必须在别人的名字前加上@符号来通知他。
  • @KamilCuk 我明白了,所以基本上你能做的任何事情都可以让编译器捕捉到错误,对吧?
  • 是 - 静态代码分析非常优于运行时错误。

标签: c


【解决方案1】:

将指向字符串常量(又名字符串文字)的指针定义为const char * 允许编译器检测到错误的访问,如果您尝试在代码中的其他地方修改pt1 指向的内容,如*pt1 = 'A'; 中的那样,而您如果pt1 具有char * 类型,则在运行时只会有未定义的行为,这会导致某些架构崩溃,并且对其他架构造成不太明显但可能更具破坏性的副作用。

为了扩展这个主题,有时对于指针定义的const 的含义存在混淆:

const char *pt1 = "Hello"; 定义了一个可修改的指针pt1,它指向一个不能通过它修改的char 数组。因为"Hello" 是一个字符串常量,所以它是pt1 的正确类型。 pt1 可以修改为指向另一个字符串或char,可修改或不可修改,或设置为NULL

char *pt2 = "Hello"; 定义了一个可修改的指针pt2,它指向一个可以通过它修改的char 数组。尽管"Hello" 为与历史代码兼容,C 标准仍允许这样做。 gccclang 可以使用 -Wwrite-strings 命令行选项禁用此行为。我强烈建议使用此警告和更多警告以避免常见错误。

const char * const pt3 = "Hello"; 定义了一个常量指针pt3,它指向一个不能通过它修改的char 数组。 pt3 不能修改为指向另一个字符串,甚至不能设置为NULL

char * const pt4 = "Hello"; 定义了一个常量指针pt4,它指向可以通过它修改的char 数组。 pt4 初始化后无法更改。

charconst 可以按任意顺序排列,但const 是在* 之前还是之后会有很大的不同。

【讨论】:

    【解决方案2】:

    上面的const有什么用?

    const char* pt1 = "Hello";
    

    仅表示您无法更改 pt1 指向的数据。

    两者

    const char* ptr1 = "Hello";
    char* pt2 = "Goodbye";
    

    为字符串文字创建静态内存。我建议你阅读this

    所以优点是你总是会在第一次出现编译时错误,而第二次它可能取决于编译器。一些编译器会自动执行此操作。查看我链接到的页面。

    【讨论】:

      【解决方案3】:

      为什么对字符串使用const char* 形式

      当引用的字符串不应被修改时使用const char *ptr1,并允许编译器基于此进行优化。

      使用 字符串字面量进行赋值时总是如此。

      当引用的字符串可能被修改时使用char *ptr2

      char* pt2 = "Goodbye"; 的危险在于后面的代码可能会尝试更改 pt2 引用的数据,该数据目前指向 字符串字面量

      【讨论】:

        【解决方案4】:

        为什么对字符串使用 const char* 形式

        通知自己和其他开发人员指针指向的内存不能被修改。在这种情况下,const 是一个关键字,主要是程序员通知程序员指针指向的数据是const

        基本上你能做的任何事情都可以让编译器捕捉到错误,对吧?

        是的。这就是开发人员推动发明更好的静态代码分析工具的原因。 There are many tools 用于静态代码分析,最近 GNU 编译器 gcc 11 自带了内部代码静态分析。这也是为什么像Rust 这样的语言被发明并如此流行的原因。所有工具都试图将尽可能多的错误推送到“静态”可检测到 - 在编译时。

        Gcc 还有一个带有 -Wwrite-strings 的警告,它会警告像 char *str = "str" 这样将 const 文字分配给非常量指针的代码。

        【讨论】:

        • “通知自己和其他开发人员”,我会说自己,其他开发人员和编译器。 +1 总体答案虽然!!!
        【解决方案5】:

        正如 KamilCuk 指出的那样,修改 const char* pt1 = "Hello"; 已经在编译时给您一个错误,此时您可以修复代码,重新编译,一切都很好。修改char* pt1 = "Hello"; 会在运行时引发错误,并且您不希望所有 100 万用户重新下载并重新安装您的程序(您必须首先为此购买更好的互联网连接)。所以,你绝对应该使用const char*

        【讨论】:

        • 您的解释有些混乱:以一种或另一种方式定义pt1 不会导致错误,但将其定义为const char* pt1 = "Hello"; 将允许编译器在代码中的其他位置检测到错误访问您尝试修改pt1 指向的内容,如*pt1 = 'A';
        • @Rob 我确实没有要求 OP 澄清,我没有批评他;这确实提供了这个问题的答案!
        猜你喜欢
        • 1970-01-01
        • 2021-12-26
        • 1970-01-01
        • 2010-09-21
        • 2014-05-16
        • 2020-01-03
        • 2019-12-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多