C语言类型的字符串怎么判断为空

这篇文章涉及到空指针常量,结合前面写的一起看,地址为: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函数出现段错误。

在不同的系统中,NULL并非总是和0等同,NULL仅仅代表空值(可以参考 https://blog.csdn.net/qq_31930499/article/details/80166472),也就是指向一个不被使用的空地址( 在大多数系统中,都将0作为不被使用的地址)。 在没有将p指向别的有效地址前,判断p是否为空只能if(p == NULL), 不能使用 strlen(p)==0等函数,不然会段错误。标准做法是:
if(p != NULL){
   if(strlen(p) == 0)

        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字符串好用啊!

猜你喜欢

转载自blog.csdn.net/qq_31930499/article/details/80465524