请在(且只能在TC2.0)中运行下面代码,先不要看结果,想想会得到什么:
#include<stdio.h> #include<stdlib.h> // 文章要求代码在Tc下运行 int main(int argn, char* argv[]) { char* szStringA = "Hello,world!"; char* szStringB = "Hello,world!"; *szStringA = \'-\'; // dev下上面的语句在执行过程中异常退出,说明dev并不允许改变字符串常量, dev下,如果查看szStringA 和 szStringB的值的话,这两个指针的值话,也是一样的 puts(szStringB); return 0; }
输出结果是:"-ello,world!";。是否和你想象的结果不一样呢?
ANSI C明确说明:修改字符串常量,效果是未定义的。
首先我们得清楚,如何才能得到字符串常量?只有一种方式:char* szString = “Hello,world!”;这个声明得到一个字符串常量。那么char szString[] = “Hello,world!”;可以吗?不可以!这样得到的是字符串变量。好了,回过来,由于ANSI C没有要求编译器实现者如何具体对字符串常量进行处理,所以有些编译器会把相同的多个字符串常量看成一个(注意:这种优化仅有可能出现在字符串常量中,不要把泛泛的用于其他类型的常量。如:int num1 = 11;int num2 = 11;虽然是两个相同的常量,但是修改num1不会影响num2),目的是为了节约内存空间,所以上面的例子中,当修改字符串a时,b也被修改了。从这里可以看出,TC2.0有对字符串常量进行优化,而其他的编译器(如:DEVC++5.0)不一定也会优化,结果可能是无法通过编译,或者通过编译但是结果是垃圾值。由于这些种种不确定因素,我们应尽量避免修改字符串常量。
如果必须修改字符串就没有办法呢?有!一定有!请注意:我们要的效果是修改字符。因此,只需要定义字符串变量,而不是字符串常量。前面说过,可以用数组的方式定义char szString[] = “Hello,world!”;;这样,在程序中就可以修改字符串了。试试下面代码:
#include<stdio.h> #include<stdlib.h> int main(int argn, char* argv[]) { char szStringA[] = "Hello,world!"; char szStringB[] = "Hello,world!"; // 这样其实是声明了一个数组大小由后面初始化常量决定的字符数组变量 *szStringA = \'-\'; puts(szStringB); return 0; }
这样的代码能够在dev下面运行,而且看起来是修改了一个常量.