本文共 2396 字,大约阅读时间需要 7 分钟。
作者:lwyang?
在 C 语言中,字符串实际上是使用 null 字符 ‘\0’ 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。
下面的声明和初始化创建了一个 “Hello” 字符串。由于在数组的末尾存储了空字符,所以字符数组的大小比单词 “Hello” 的字符数多一个。
char greeting[6] = { 'H', 'e', 'l', 'l', 'o', '\0'};
依据数组初始化规则,我们可以把上面的语句写成以下语句:
char greeting[] = "Hello";
以下是 C/C++ 中定义的字符串的内存表示:
其实,我们不需要把 null 字符放在字符串常量的末尾。C 编译器会在初始化数组时,自动把 ‘\0’ 放在字符串的末尾。那么接下来大家看以下这个程序的输出结果:
//test.c#include#include int main(){ char str[] = "12345"; char tmp1[5]; char tmp2[5]; printf("str length: %d\n",strlen(str)); strncpy(tmp1, str, 5); sprintf(tmp2, "%s", str); printf("strcpy tmp1: %s\n", tmp1); printf("sprintf tmp2: %s\n", tmp2); printf("str :%s\n, str); printf("str length: %d\n",strlen(str));}
gcc -g test.c
输出结果:
这个程序的结果非常奇怪 第一行str length : 5
没有问题,sizeof(str)= 6 第二行发现 tmp1:1234512345
然后最后发现str变为了空字符串 我们可以使用gdb进行调试分析为什么会出现这样的结果:
gdb ./a.out
启动GDB调试工具:
l 输出代码正常
start 启动程序,在main()处暂停
n 单步执行
p &str p &tmp1p &tmp2查看str, tmp1, tmp2的地址
我们可以发现str,tmp1,tmp2是连续的地址空间tmp1 tmp2 str
tmp1 = 0x7fffffffdec8
tmp2 = 0x7fffffffdecd
str = 0x7fffffffded2
tmp1 + 5 = tmp2 tmp2 + 5 = str 接下来打印从tmp1地址(0x7fffffffdec8)开始的16个字节,可以看看里面都是存的什么
x/16cb 0x7fffffffdec8
可以看到:
tmp1: '\200' '\F' 'U' 'U' 'U'tmp2: 'U' '\000' '\000' '\300' '\337'str: '1' '2' '3' '4' '5'
由于tmp1
,tmp2
没有进行初始化,因此里面的内容不能确定
str
开始的地址存放的正是“12345”
n
然后继续单步执行完strncpy(tmp1, str, 5);
x/16cb 0x7fffffffdec8
到这里我们可以看到strncpy(tmp1, str, 5);
已经起作用了,它将tmp1里面的内容替换为了“12345”
, 而tmp2
,str
里的内容是不变的
tmp1: '1' '2' '3' '4' '5'tmp2: 'U' '\000' '\000' '\300' '\337'str: '1' '2' '3' '4' '5'
strncpy 函数是没有在字符串末尾自动添加’\0’的
注:若在这里进行tmp1,tmp2,str的输出,则结果为:
n
然后继续单步执行完sprintf(tmp2, "%s", str);
x/16cb 0x7fffffffdec8
到这里我们可以看到sprintf(tmp2, "%s", str);
已经起作用了,它将tmp2里面的内容替换为了“12345”
, 而且发现在tmp2末尾自动添加了'\0'
, 即str
地址开始的字符(0x7fffffffded2)变为了'\0'
,这里就不难理解为什么str
最后的length变为了0。
tmp1: '1' '2' '3' '4' '5'tmp2: '1' '2' '3' '4' '5'str: '\000' '2' '3' '4' '5'
sprintf 函数会自动在字符串末尾添加’\0’
n
然后继续单步执行完程序
根据上面的分析结果可以看到下面最后tmp1
,tmp2
,str
里面的存的内容:
tmp1: '1' '2' '3' '4' '5'tmp2: '1' '2' '3' '4' '5'str: '\000' '2' '3' '4' '5'
tmp1
的输出为1234512345
tmp2
的输出为12345
而str
的第一个字符已经变成了结束符'\0'
,因此str输出为空,str length为0
以上通过查看内存地址分析了程序为什么会出现这么奇怪的执行结果,所以在进行字符串操作时一定要注意结束符,不然会出现意想不到的问题,如有不正确的地方还请指出来一起交流!?
转载地址:http://juhpi.baihongyu.com/