先看例子:
为什么是上图那样的结果呢?
这里有几个知识点:
1. C语言中的局部变量存储在栈里。所以p1~p6存放情况如下绿色图片。
2. 栈大家都知道是从栈底往上存东西的,栈的生长方向向上的,这是形象的说法;若从地址大小上来说,这里栈是从到 高地址乡低地址的地方生长(可以自己写程序判断栈的生长方向)
3,但对于变量个体来说存放顺序是向下的,低地址到高地址(这里又涉及到大小端模式,很明显这里是大端模式)
简单解释一下:
大端:低地址存储高位字节,高地址存放低位字节
(符合人平时的书写顺序:比如写78,地址可以理解为顺序,先写7再写8,由小序号到大序号,但小序号写 的是7,7是十位,是高位,也就是高字节。。。)
小端: 反之
4. %s打印默认是遇到\0结束
所以现在我们就可以理解p3为什么是那样的打印,因为p3没有结束符,他会顺着地址一直打印,知道p2的结束符
p3前面的乱码是因为,我们赋值的是数字1,2,3,相当于是askll码了,对应的字符就是那个正方形方框,至于后面的烫烫打印是因为p2的大小15字节,而赋值的字符串长度是11,其余的是随机值,编译器在运行时对这种默认赋值oxcc,对应的字符就是烫
总结:
所谓的乱码、重叠,覆盖,均是数组越界了。如果给数组拷贝时,不注意大小,没有结束符\0,就有可能出现乱码,覆盖重叠。
知道了局部变量是如何存放的,就是连续放在栈上,如果数组越界,就是占了别的变量的位置,那能不发生乱码,覆盖吗?
用法总结
无论是哪种拷贝函数,都要注意这个这个\0的存在,
只不过,memcpy限制了长度,只要输入的没错,不至于导致程序崩溃,但是strcpy就要很注意子符串有无\0,否则很容易越界访问引起程序崩溃。
- 解决:
- 只要记住以下两点,就不会出错
1.对于目的数组,拷贝之前可以都初始化为0,这就相当于给他加了\0
2.还有一个大前提,目的数组的长度最好大于等于源数组长度。
满足以上两个条件,就不会越界啦!!!