这篇文章涉及到空指针常量,结合前面写的一起看,地址为:https://blog.csdn.net/qq_31930499/article/details/80166472
最近在xcode IDE下编程,遇到一个问题。平时我们判断C语言类型的字符串是否为空,如下
char *p; ... if(p == "") ...
但是会提示警告:Result of comparison against a string literal is unspecified (use strncmp instead)。当时我就愣住了,因为以前没有特别注意,但是为什么会有警告?(虽然没有错误,但是运行就会发现有问题)
可能会跟编译器有关系。然后我在Cygwin编译器和linux系统gcc编译器编译都没有问题。所以判断是跟编译器有关系。
但是真的是只是和编译器有关系吗?
其实,p == "",是比较是指针所指向的地址是否相等,除非p在比较之前,有p = ""这个语句赋值,不然p 是不可能等于""这个的。详细请看第(4)步。
由此,进一步深究。
(1)不同的编译器和环境,局部变量有的会初始化(Cygwin),有的不会(gcc,但是会指向一个不确定的值)。所以
char* p; printf("%p\n",p); printf("%p\n",&p); printf(">>>%s\n",p);
Cygwin中: 等同于 char* p = NULL。
0x0
0xXXXXXXXX
>>>(null)
gcc:等同于 char *p; p指向了一个不确定的地址。
0xYYYYYYYY
0xXXXXXXXX
(可能是乱码或者空)
注意:全局变量如果没有初始化,编译器都会初始化。
(2)在gcc编译器中,将上述代码改成下面
char* p=NULL; printf("%p\n",p); printf("%p\n",&p); printf(">>>%s\n",p);
结果和Cygwin表现“一样”,当然地址肯定不一样。
再将上述代码修改成:
char* p=NULL; printf("%p\n",p); printf("%p\n",&p); printf(">>>%s\n",p); if(strlen(p) == 0) return -1;
运行,则运行到strlen函数出现段错误。
printf("empty");
注意:
如果是字符串指针,首先要判断指针是否为空(这个很重要,请看上面出现段错误),否则容易造成段错误。
养成良好变成习惯,定义变量后首先要初始化。
(3)NULL与“”区别
空字符串是“”,会创建一个对象,内容是“”,有内存空间
而NULL,不会创建对象,没有内存
(4)那么如何比较字符串是否相等?
先看下面这个程序:
char *p = (char *)"111"; if(p == "111") cout << "== Equal" <<endl;
编译和执行都正确。也能正确表示两个字符串是否相等。
再看:
char p[] = {'1','1','1','\0'}; if(p == "111") cout << "== Equal" <<endl; //不执行 if(strcmp(p,"111") == 0) cout << "strcmp Equal" <<endl; //执行
为什么p == "111"不相等,但是使用比较函数strcmp比较却是相等?
原因是前者,只是比较 p指针指向的地址 是否等于 "111"字符串的首地址(明显"111"是文字常量区的数据,p是指向栈区的数据地址,所以肯定不一样)
后者只是比较字符串内容是否相等,显然内容是一样的。
总之,还是C++的string字符串好用啊!