others - c - 不使用strcmp()进行字符串比较

strcmp可以比较字符串内容,因此它更受欢迎,if (str1 == str2)

如果是这样,那么为什么if条件会在下面的C代码中得到满足?


 char *p2="sample1";


 char* str[2]={"sample1","sample2"};



 if(p2==str[0])


 {


 printf("if condition satisfiedn");


 }



GDB :


(gdb) p p2


$1 = 0x4005f8"sample1"


(gdb) p str[0]


$2 = 0x4005f8"sample1"


(gdb) p &p2


$3 = (char **) 0x7fffffffdb38


(gdb) p &str[0]


$4 = (char **) 0x7fffffffdb20


(gdb) p *p2


$5 = 115 's'



时间:

你已经声明了三个字符串:

  • sample1p2指向
  • sample1str[0]指向
  • sample2str[1]指向

因为这些都是"字符串文字",所以不能更改,并且只能存储为只读。

允许编译器识别你实际上只有两个唯一的字符串,因此只存储两个字符串(这取决于实现)。

什么是0x4005f8

你将在内存中发现的可能类似于以下内容:


0x0000004005f8 's'


0x0000004005f9 'a'


0x0000004005fa 'm'


0x0000004005fb 'p'


0x0000004005fc 'l'


0x0000004005fd 'e'


0x0000004005fe '1'


0x0000004005ff ''


0x000000400600 's'


0x000000400601 'a'


0x000000400602 'm'


0x000000400603 'p'


0x000000400604 'l'


0x000000400605 'e'


0x000000400606 '2'


0x000000400607 ''


...


0x7fffffffdb20 0xf8


0x7fffffffdb21 0x05


0x7fffffffdb22 0x40


0x7fffffffdb23 0x00


0x7fffffffdb24 0x00


0x7fffffffdb25 0x00


0x7fffffffdb26 0x00


0x7fffffffdb27 0x00


...


0x7fffffffdb38 0xf8


0x7fffffffdb39 0x05


0x7fffffffdb3a 0x40


0x7fffffffdb3b 0x00


0x7fffffffdb3c 0x00


0x7fffffffdb3d 0x00


0x7fffffffdb3e 0x00


0x7fffffffdb3f 0x00



也就是说:

  • p2变量:
    • 位于地址0x7fffffffdb38
    • 0x4005f8
  • str[0]变量:
    • 位于地址0x7fffffffdb20
    • 0x4005f8
  • 内存地址0x4005f8sample1字符串的开头,即: s字符
  • 内存地址0x4005f9sample1字符串的下一个特征,即: a字符
  • 0x4005fam
  • 0x4005fbp
  • 0x4005fcl
  • 0x4005fde
  • 0x4005fe1
  • 0x4005ff的或"nul",终止字符串,

测试p2 == str[0]时,测试存储在两个变量中的值是否相同,这些值是字符串的基地址,它们保存着相同的字符串,因此保持相同的值。

存储"相同"字符串是完全可行的(即: 在两个不同的内存位置中的相同文本,在这种情况下,这个测试会失败。

在这个有效地说,两个字符串是"相同实例",它们位于内存中的相同位置,因此必须有相同的内容。

怎么打印它?

可以使用x/1c作为单个字符打印,或者使用x/1s (gdb正确处理字符串)作为一个字符串终止字符串。

main.c:


#include <stdio.h>


#include <stdlib.h>



int main(int argc, char *argv[]) {


 char *p2 ="sample1";


 char *str[2] = {"sample1","sample2" };



 if (p2 == str[0]) {


 printf("truen");


 }



 return 0;


}



编译:


gcc main.c -o main -g



运行:


$ gdb ./main


[...]


(gdb) start


Temporary breakpoint 1 at 0x4005a5: file main.c, line 4.


Starting program: /home/attie/stackoverflow/56475101/main



Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe418) at main.c:4


4 int main(int argc, char *argv[]) {


(gdb) list


1 #include <stdio.h>


2 #include <stdlib.h>


3


4 int main(int argc, char *argv[]) {


5 char *p2 ="sample1";


6 char *str[2] = {"sample1","sample2" };


7


8 if (p2 == str[0]) {


9 printf("truen");


10 }


(gdb) b 8


Breakpoint 2 at 0x4005cc: file main.c, line 8.


(gdb) c


Continuing.



Breakpoint 2, main (argc=1, argv=0x7fffffffe418) at main.c:8


8 if (p2 == str[0]) {


(gdb) print p2


$1 = 0x400684"sample1"


(gdb) print str[0]


$2 = 0x400684"sample1"


(gdb) print str[1]


$3 = 0x40068c"sample2"



从地址0x400684打印三个"字符串":


(gdb) x/3s 0x400684


0x400684:"sample1"


0x40068c:"sample2"


0x400694:"true"



从地址0x400684打印16个字符:


(gdb) x/16c 0x400684


0x400684: 115 's' 97 'a' 109 'm' 112 'p' 108 'l' 101 'e' 49 '1' 0 '00'


0x40068c: 115 's' 97 'a' 109 'm' 112 'p' 108 'l' 101 'e' 50 '2' 0 '00'



打印存储在p2str[0]str[1]上的地址:


(gdb) x/1a &p2


0x7fffffffe308: 0x400684


(gdb) x/1a &str[0]


0x7fffffffe310: 0x400684


(gdb) x/1a &str[1]


0x7fffffffe318: 0x40068c



0x4005f8是存储字符串常量的地址,你可以用printf类型转换"%p"打印它,需要一个void*参数,你的完整语句将是:


printf("p2 = %pn", (void*)p2);


printf("str[0] = %pn", (void*)str[0]);



GCC不需要对void*进行强制转换,但是可以将它们包括在一起以便删除警告,当将指针作为变量参数列表的一部分传递时,编译器不会将它隐式转换为void * 。

...