在说c的字符串之前,先来看看另一个东西,字符数组。这两者的区别搞清楚了,看到字符串后,就不会有那种模模糊糊的感觉了。
字符数组的基本形式为:
char CharArray[5]={'h','e','l','l','o'};
可以看到上面的形式就是一般的数组初始化形式。
如果改成:
char CharArray[6]={'h','e','l','l','o','\0'};
这其实就是一个c风格的字符串,上面的形式可以完全等价于:
char *CharArray ="hello";
下面主要来讲一下c的字符串的两种初始化方式
1、char *p1 = "Hello";
2、char p2[] = "Another Hello";
我有很长一段时间把形式2当做了字符数组,其实他也是一种字符串形式。其实本来文章到这里也差不多了,但是还有一些小细节需要注意一下,比如说,形式1中的字符串是不能修改的,但是形式2中的字符串是可以修改的,这是为什么呢?
直接简单粗暴一些吧,上反汇编代码:
(看不懂汇编的同学没关系,可以直接看我下面的解释)
char *p1 = "Hello"; //直接将常量区中字符串对应的地址赋值给p1
0113A3AC mov dword ptr [ebp-48h],offset string "Hello" (118AF10h)
char p2[] = "Another Hello.";//将常量区中对应的字符串,以4个字节为单位,一个一个复制到栈内存中,最后局部指针p2指向这片内存
0113A3B3 mov eax,dword ptr [string "Another Hello." (118AEFCh)]
0113A3B8 mov dword ptr [ebp-60h],eax
0113A3BB mov ecx,dword ptr ds:[118AF00h]
0113A3C1 mov dword ptr [ebp-5Ch],ecx
0113A3C4 mov edx,dword ptr ds:[118AF04h]
0113A3CA mov dword ptr [ebp-58h],edx
0113A3CD mov ax,word ptr ds:[0118AF08h]
0113A3D3 mov word ptr [ebp-54h],ax
0113A3D7 mov cl,byte ptr ds:[118AF0Ah]
0113A3DD mov byte ptr [ebp-52h],cl
常量区内的内存:
0x0118AEEB 73 65 00 00 00 6a 69 6e 6c 61 69 00 00 25 78 0a 0041 6e 6f 74 68 65 72 20 48 65 6c 6c 6f 2e 00 00 00 00 00 00 se...jinlai..%x..Another Hello.......
0x0118AF10 48 65 6c 6c 6f 00 00 00 63 6d 64 2e 65 78 65 00 00 00 00 00 2f 63 00 00 2a 00 63 00 6f 00 6d 00 6d 00 61 00 6e Hello...cmd.exe...../c..*.c.o.m.m.a.n
栈空间中的内存:
0x0044F78D cc cc cc cc cc cc cc 41 6e 6f 74 68 65 72 20 48 65 6c 6c 6f 2e 00 cc cc cc cc cc cc cc cc cc 10 af 18 01 cc cc ???????Another Hello..?????????.?..??
解释:
上面的汇编的大致意思是,形式1 char *p1 = "Hello",直接将常量区中字符串对应的地址赋值给p1,在栈空间中10 af 18 01就是p1存储的地址,上面我把反汇编后的Hello的地址标成蓝色了,因为小端的缘故(不懂小端是什么的话就问一下度娘吧),所以这个地址其实就是常量区中Hello对应的地址,所以用如*p1 ='h'这种操作是不行的,因为p1指向的是常量区的内存,常量区的内存是不允许修改的,在编译期间就已经确定了。
形式2 char p2[] = "Another Hello.",细心的同学可以看到常量区内Hello和Another Hello都存在,而Another Hello存在于占空间的内存中,这是因为形式2是将常量区中对应的字符串,以4个字节为单位,一个一个复制到栈内存中,最后局部指针p2指向这片栈内存。所以*p2 =‘h’,这个操作是允许的,因为这修改的是栈内存中的内容。
如有错误,欢迎指正
===================2017/11/8 更新========================
下面评论的这位大兄弟,我测试了一下,没有问题啊