为什么在使用 strtok() 时会在此处修改常量 char 数组

why constant char array is modified here when strtok() is used

#include <stdio.h>

int main() {
    const char a[99]="hello-hi";
    printf("%s\n",a);
    char *p=strtok(a,"-");
    printf("%s",a);
    return 0;
}

输出:

hello-hi
hello

这里为什么要修改a??我把它设为 const 但为什么它仍然被修改了??

1. const char数组不必在只读内存中。试图修改它是一种未定义的行为。段错误、修改、病毒激活、银行账户转移、磁盘擦除等任何事情都可能发生

  1. 阅读编译器警告
<source>:9:20: warning: passing 'const char [99]' to parameter of type 'char *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
    char *p=strtok(a,"-");
  1. int main() 应该是 int main(void)

why a is modified here??

strtok 修改字符串。修改 const object 会导致未定义的行为。示例程序的行为未定义。

事实上,const 数组并没有转换为指向non-const 的指针(没有转换),所以程序是ill-formed。


其他问题:

  • 您没有包含声明 strtok 的 header。
  • int main() 在 C.
  • 中是 non-standard

来自 C 标准(6.7.3 类型限定符)

6 If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.

编译器至少应发出警告,指出 strtok 的调用会从传递的参数表达式中丢弃限定符 const

strtok

的这个调用中
char *p=strtok(a,"-");

数组 a 被隐式转换为 const char * 类型的指针指向它的第一个元素,而函数的相应参数没有限定符 const.

const的定义不是“电脑会阻止你修改对象”。 C 2018 6.7.3 7中const的定义是:

If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined…

因此,使用 const 定义一个对象不会让计算机向您承诺该对象不会被修改。它实际上是另一个方向的承诺:它是您对计算机的承诺,您不会尝试修改该对象。这允许编译器将对象放入标记为只读的内存中。

如果你违反了承诺,那么这个行为是C标准没有定义的。该对象可能在只读内存中,尝试修改它会导致陷阱并提醒您程序中的错误。或者该对象可能在可修改的内存中,并且尝试修改它会修改它。或者,通过程序优化,可能会出现其他行为。

C 标准确实在这方面给了你一些帮助。当您将 const char * 传递给 strtok 时,它需要 char *,编译器需要发出诊断消息。注意编译器报告的警告和错误,并使用它们来修复您的程序。最好使用编译器开关将警告提升为错误。 (-Werror 使用 GCC 或 Clang,/WX 使用 Microsoft Visual C++。)