- 第一段说:“在C文字表示固定值”。
我不知道作者意图,而是从一个字符串运行期间字面所产生的阵列的修改是公然不确定,根据C11/6.4.5p7:“如果程序试图修改这样的数组,行为是不确定的。“
还应当指出的是,试图修改在运行时间期间一个字面const
-qualified化合物也将导致未定义的行为,其说明沿侧一些volatile
在C11/6.7.3p6 - 相关未定义行为。否则,它会很好地定义修改复合文字。
例如:
char *fubar = "hello world";
*fubar++; // SQUARELY UNDEFINED BEHAVIOUR!
char *fubar = (char[]){"hello world"};
*fubar++; // This is well defined.
字面上"goodbye galaxy"
"hello world"
替换,在任一种片是源代码,是好的。然而,重新定义标准函数(即#define memcpy strncpy
或#define size_t signed char
,这两种方法都是破坏某人日的好方法)是未定义的行为。
- 由于字符串文字不是复合文字,应该修改字符串文字吗?
从一个字符串产生的数组当然应该不运行期间进行修改,任何试图这样做会引发未定义的行为。
另一方面,字符串字面本身作为引用的字符序列存在,当然,这可以根据您的选择进行修改。尽管如此,你不是有责任来修改它。
第二段说编译器做的时候“C不严格禁止修改字符串文字”。所以应该修改字符串文字?
C标准没有严格禁止很多未定义的行为;它留下的行为undefined,这意味着您的程序可能表现不正常或不可移动。在良好限定C的领域,你的程序不应以任何未定义行为,包括由多线程溢流阵列,const
修改对象-qualified或从字符串文字所得,竞态条件的阵列等。
如果你想调用未定义的行为,C会让你在脚下自拍。你可能有充足的理由这样做;也许你的程序会更优化,或者你的编译器实际上可以让你修改字符串文字(他们说,“这是一个功能,而不是一个bug”,所以给我们你的钱,“他们说,当你变得依赖他们的非标准怪癖)。请注意,某些编译器会改为表现为尝试修改未发生或崩溃,或者可能会导致一些漏洞。
...还有一点,请注意,您的代码将不再符合C代码!
这两段相互矛盾吗?
由于遗漏,也许。第一段确实说明了这些值是固定的,并且值可能的第二段通过调用未定义的行为在运行时期间可以修改。
我认为作者的意图是区分源代码和运行时环境的元素。例如,他/她可以简单地通过确保明确说明文字在运行时间不应该被修改来澄清。
我该如何理解它们?
在C这种值的领域不能在运行时期间变化,因为调用未定义的行为是指所讨论的代码不再符合C代码。
也许他们试图避免解释未定义的行为,因为它可能看起来太复杂,无法解释。如果你更深入地研究这个主题,你会发现,正如预测的那样,意义大致上是这两个词的连接。
undefined:/ʌndɪfʌɪnd/ adj。不清楚或定义。 行为:/bɪheɪvjə/名词。机器或自然现象的工作方式或功能
也就是说,尝试在运行时修改由字符串文字产生的数组导致“功能不清晰”。它不需要在计算机科学领域的任何地方记录下来,即使有文档记录,文档也可能是谎言。
是否可以修改既不是复合字面也不是字符串的文字?
作为源代码中的词汇元素,提供它不会覆盖标准符号,是的。文字不是l值(即没有任何存储),例如整数常量,显然不能在运行时修改。我想可能在某些系统上试图修改函数指针指向的内存,这可能被看作是文字;这也是不确定的行为,并会导致代码不是C.
它也有可能修改许多其他类型的元素未被视为对象 C标准,如回地址在堆栈。这就是缓冲区溢出如此危险的原因!
所有书籍谎言。只相信标准。 – o11c
谢谢。我会牢记这一点。我认为这本书严格遵循标准,并以更容易理解的方式解释标准。 – Tim
字符串文字可能会更改,但更改的结果未定义。 – BLUEPIXY