想破脑袋也不知道这句为什么会被爆出'char类型作为下标'的警告

 我来答
你猜我猜哇擦猜
2016-04-03 · TA获得超过2.8万个赞
知道大有可为答主
回答量:2万
采纳率:0%
帮助的人:6706万
展开全部
C语言的局部变量默认为自动变量。
而自动变量默认是在“栈”上。之所以出现"123456789,56789"这样的输出,是
因为在你的系统下“栈”是由高地址向低地址增长的。所以d的地址比s的地址要低,在自负串拷贝超出d范围时,就会覆盖位于高地址的s. 因为d还有一个字符串标志"\0", 所以d的地址比s地址低4个字节。所以超出4个字节的部分(56789)会覆盖d.

把代码改成这样,看得会更清楚:
int main(void)
{
char s[] = "123456789";
char d[] = "123";
printf("%p %s\n", s, s);
printf("%p %s\n", d, d);

strcpy(d, s);
printf("%s,%s\n",d,s);

return 0;
}
0022FF40 123456789
0022FF3C 123
123456789,56789

这里地址在不同的系统下可能不同,但一般32位win下相对地址是一样的,地址差是4。以这里的输出为例子,
可见栈的结构是:
...
0022FF48 9
0022FF47 8
0022FF46 7
0022FF45 6
0022FF44 5
0022FF43 4
0022FF42 3
0022FF41 2
0022FF40 1 /* s开始 */
0022FF3F \0
0022FF3E 3
0022FF3D 2
0022FF3C 1 /* d开始 */

拷贝发生时,从0022FF3C开始覆盖123456789, 可见1234覆盖了0022FF3C- 0022FF3F四个字节, 这四个字节属于d的范围. 56789\0覆盖了 0022FF40 - 0022FF45 六个字节,这六个字节属于s的范围。 这样内存变为:
0022FF48 9
0022FF47 8
0022FF46 7
0022FF45 \0
0022FF44 9
0022FF43 8
0022FF42 7
0022FF41 6
0022FF40 5 /* s开始 */
0022FF3F 4
0022FF3E 3
0022FF3D 2
0022FF3C 1 /* d开始 */

可见, d的'\0'被覆盖,从0022FF3C开始,第一个字符串结束标志位于0022FF45, printf("%s\n", d)会输出完整的字符串"123456789"。而printf("%s\n", s);则会从0022FF40开始输出直到在0022FF45遇到'\0', 于是会输出s被覆盖的六个字节"56789".这就解释了为何printf("%s, %s\n", d, s)会输出123456789,56789,
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式