关于字符串数组输入输出和内存分配问题

关于字符串数组输入输出和内存分配问题

C语言字符串数组的正确使用是处理字符问题的根本,但是由于C语言本身的特性,字符串数组有很多的使用细节需要注意,下面将以字符串数组输入输出问题为切入点,并且引出字符串数组在内存中的分配和字符写入顺序问题:

先举一个简单的例子:

定义字符串数组,并读入输出(为了看清楚字符串数组读取到了哪个位置,以##为末尾提示符):

char word1[7];
char word2[7];

scanf("%s",word1);
scanf("%s",word2);

printf("%s##%s##\n",word1,word2);

这是一个很简单的程序,定义两个最多能读入六个字符的字符串数组,并分别读入字符,输出。

下面我们用四组特殊数据来测试这段代码:

第一组:

123456
123456
123456##123456##

读入的数据长度为6位,这是正常情况。

第二组:

12345678
12345678
12345678##12345678##

我们尝试将要读入的数据扩大成8位(此时字符串数组已经“溢出”),但我们仍看到了我们想要的结果。

第三组:

123456789012345
123456789012345
123456789012345##123456789012345##

再次扩大要读入数据的长度至15位,运行一切正常。

第四组:

1234567890123456
1234567890123456
##1234567890123456##

再次扩大要读入数据的长度至16位,神奇的事情发生了:
原本先读完数据的word1似乎“没储存任何数据”word2则输出了完整的16位字符

我们试着进行分析:

  • 在编译阶段,word1和word2被分配了空间,但是这两个空间的排序是怎样的?空间大小又是怎样的?

  • 如果word1和word2的内存地址是紧挨着的,有没有可能写入溢出的数据时会互相产生影响,从而导致word1中不输出任何内容?

  • 既然C语言中的字符串输出是以字符串数组中的结尾“\0”为终止符,如果word1数组中第一个字符就是“\0”的话,word1就不会输出任何内容

  • “\0”的首位置出现说明word1的数据一定在运行时被二次写入并覆盖了

我们修改代码来验证猜想:

char word1[7];
char word2[7];

scanf("%s",word1);
scanf("%s",word2);      
printf("%s##%s##\n",word1,word2);

printf("word1的地址是     %d\n",word1);
printf("word1[1]的地址是  %d\n",&word1[1]);
printf("word1[15]的地址是 %d\n",&word1[15]);

printf("word2的地址是     %d\n",word2);
printf("word2[1]的地址是  %d\n",&word2[1]);
printf("word2[15]的地址是 %d\n",&word2[15]);

return 0;

%d与数组一起使用时会输出数组第一个元素的内存地址,我们便可以知道两个数组的首地址关系和各元素的地址关系,下面我们运行试试看:

1234567890123456
1234567890123456
##1234567890123456##
word1的地址是     6487616
word1[1]的地址是  6487617
word1[15]的地址是 6487631
word2的地址是     6487600
word2[1]的地址是  6487601
word2[15]的地址是 6487615
  • 这两个内存地址相差16个字节,说明每个word数组长度为16个字节

  • 需要注意的是,word1的地址大于word2的地址;而内存地址的排列可以看做自上而下的,即word1在下部,word2在上部

  • word[0]到word[15]的地址依次增大,说明单个字符串数组写入数据是自上而下的

可以用下面的表格来示意:

数组元素内存地址字符内容
word2[0]64876001
word2[1]64876012
word2[14]64876145
word2[15]64876156
word1[0]6487616\0
word1[1]64876172
word1[2]64876183
word1[14]64876305
word1[15]64876316

结论:

  • 很明显,位于底部的word1数组自上而下写入了1234567890123456之后,溢出的“\0”写入了下面不知名(未定义)的内存中,而位于上部的word2数组也自上而下写入1234567890123456之后,末尾的“\0”则写入了word[15]中,导致wor1的输出为空

  • 需要说明的是,这段代码在x64位电脑中运行,编译器默认分配的字符串数组空间是16位,在不同的运行环境(编译器)中会有差别

以上是我的理解,欢迎补充和指正!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值