1. 初学者经常被这个问题所困惑: char *p="abc"==>"abc"是一个const char*,为什么能够赋值给char *呢?
2. 很多论坛上都可以看到这样的提问帖,不过这些帖子有的讲的是错误的,有的虽然是对的,但是讲的不细致,初学者不好理解。对此,我根据我的经验,以及CSDN上的一些帖子仔细地说一下其中的道理。
3. 按照 C/C++ 标准的描述,"abc" 是 string literal (字符字面量、字符文字量),具有静态存储性质,类型是数组类型,并且不能被改变。注意:"abc" 是一个数组类型的对象,是左值。当然左值可以转化为右值使用,就像数组类型的对象可以转化为指针一样。
4. 虽然 "abc" 是数组类型,但是 C 和 C++ 在类型规定上是有区别的:在 C 中,"abc" 的类型是 char [4];在 C++ 中,其类型是 const char [4]。 由于数组类型可以转换为指针类型来使用,所以在 C 和 C++ 中 "abc" 可分别作为 char* 及 const char* 使用。
5. 为了兼容c中char *p="abc"这种现象的存在,C++特别允许初始化时const char*到char*的自动转换。但是这条规则被 C++ 标明为 “Deprecated”,不被推荐使用。
6. 综上所述,在 C 中:char *p="abc"是完全合乎规则的事情,在 C++ 中:由于有特殊规定,所以这样也可以。
但在c++中要注意:char *p="abc" 能不能编译通过要看你使用的编译器。鉴于大量遗留代码的存在,大部分编译器允许其通过,或者给个警告。当然,程序员自己必须保证绝不去修改其值:
A. 程序员不应该在代码中出现*p='A'这样的语句。这是当初约定好了的:编译器允许char *p="abc"通过,而程序员保证不去修改它。
B. *p='A'编译时应该允许通过,因为单就这条语句而言,它完全合法。
C. 运行时*p='A'能不能通过要看实际的运行环境,包括你使用的操作系统、编译器、编译器选项 等等,一句话,其运行结果由不得你,且不应该由你去关心,因为这种行为本身已经违反约定了。
例:当我们修改字符串常量类型的指针变量时,编译器会提示程序出错的。下面来具体讲一讲这种类型的错误。
程序1:
#include <string.h>#include <stdio.h>int main(){ //char str[5]="good"; char *str="good"; char *strtemp=NULL; printf("The string befor reversal: %s\n",str); strtemp=strrev(str); printf("The string strtemp reversed is: %s\n",strtemp); return 0;}
当我们用VC++编译时,会终止程序,并且弹出这样的提示信息:
但是这样的提示还是不够清楚,我们可以换个编译器,
程序2:
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <stdio.h>#include <string.h>int _tmain(int argc, _TCHAR* argv[]){ char *forward = "string"; printf("Before strrev(): %s\n", forward); _strrev(forward); printf("After strrev(): %s\n", forward); return 0;}
VS2013会终止程序,并且弹出这样的提示信息:
其实在程序中,我们已经修改了字符串常量指针,所以编译器会弹出提示信息,并且程序不能正常运行。
在程序1中,有这样几句代码:
char *str="good"; char *strtemp=NULL; printf("The string befor reversal: %s\n",str); strtemp=strrev(str);
系统函数strrev( )已经修改了字符串指针变量str的值,所以程序会出现修改常量的错误。
在程序2中:
char *forward = "string";printf("Before strrev(): %s\n", forward);_strrev(forward);printf("After strrev(): %s\n", forward);
这几句代码也是犯了同样的错误。
所以可以将程序1修改如下:
#include <string.h>#include <stdio.h>int main(){ char str[5]="good"; //char *str="good"; char *strtemp=NULL; printf("The string befor reversal: %s\n",str); strtemp=strrev(str); printf("The string strtemp reversed is: %s\n",strtemp); return 0;}
此程序在VC++6.0的运行结果如下:
此处用字符数组代替了字符串指针常量,而数组的值是可以修改的。