为什么在使用 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
数组不必在只读内存中。试图修改它是一种未定义的行为。段错误、修改、病毒激活、银行账户转移、磁盘擦除等任何事情都可能发生
- 阅读编译器警告
<source>:9:20: warning: passing 'const char [99]' to parameter of type 'char *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
char *p=strtok(a,"-");
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++。)
#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
数组不必在只读内存中。试图修改它是一种未定义的行为。段错误、修改、病毒激活、银行账户转移、磁盘擦除等任何事情都可能发生
- 阅读编译器警告
<source>:9:20: warning: passing 'const char [99]' to parameter of type 'char *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
char *p=strtok(a,"-");
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++。)