鱼C论坛

 找回密码
 立即注册
查看: 1845|回复: 4

s1e19测试题2的一点疑问

[复制链接]
发表于 2022-7-8 15:59:56 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 顶级太阳 于 2022-7-8 16:02 编辑

小甲鱼在s1e19测试题2中提出要求,指出代码里面的问题。并给出了代码如下。答案里指出这个代码会造成字符串连接过程中超出数组定义的空间。很好奇,抄下来运行了一下,同时增加了一个输出数组的语句,结果让我很是吃惊。
#include<stdio.h>
#include<string.h>
int main()
{
        char str[10];
        strncat(str,"I love FishC.com!",sizeof(str));
        printf("%s\n",str);
        printf("%ld\n",sizeof(str));

return 0;
}

运行结果如下:
屏幕截图 2022-07-08 155317.jpg

结果中,输出数组结果前面多了一个“@”符号。数组str[10]没有进行初始化,开始考虑是某一个不可预知的初始值,后来考虑是直接连接的,那么程序认为数组里应该是没有数据的,应该是从第一个字符开始填入,也就是str[0],那么应该没有这个字符存在。不同时段,重复开关机测试结果都是这样。而且下一句测试数组长度,输出为10,表示数组大小并没有改变,人工数了连接进去的字符,也是10个。输出11个字符,这个我可以理解,毕竟连接后,结束符在接入的10个字符的后面。那么问题就集中到了最前面的“@”是怎么来的了。求教,最前面的“@”怎么出现的?


补充一下:我用的系统是虚拟机Ubuntu16.4.6系统。是不是和这个有关?主要是小甲鱼的答案里没有提这方面的事。很不明白。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-7-8 16:10:58 | 显示全部楼层
我运行没有问题
run.png
可能真的跟你的虚拟机有关系
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-7-8 17:49:31 | 显示全部楼层
1.声明了一个数组,那么它的内存大小就是固定的,不要以 %s 打印出 str 看到10个以上的字符,就以为数组变大了。%s 本就是以 str 作为首地址,以 '\0' 作为结束标志,根本不管是否在str的合法空间。

2.内存里不管你是否初始化,都是有数据的,只是你自己不初始化就无法预测到内存里的数据是什么内容,也就是脏数据。所以不存在什么认为数组里没数据,就从str[0]开始连接。

3.strncat() 本质就是连接2个字符串,也就是找到第一个字符串的末尾(即'\0'),将第二个字符串填入后面的内存空间。以 str 为首地址往后找,直到找到 '\0',在你不初始化的情况下,后面10字节空间(即数组合法空间)可能会有 '\0',也可能没有,就算没有也会继续往后找,直到在内存中发现 '\0',将第二个字符串接入。之后你用 %s 打印同理,你看到的原第二字符串的内容,未必就存在那10字节的数组空间中。而原第一字符串的脏数据就会导致第二字符串前乱码的出现
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-9 09:23:50 | 显示全部楼层
风车呼呼呼 发表于 2022-7-8 17:49
1.声明了一个数组,那么它的内存大小就是固定的,不要以 %s 打印出 str 看到10个以上的字符,就以为数组变 ...

1、我用%s打印str字符串纯粹是为了好奇在没有初始值的情况下会发生什么,并没有感觉数组变大了。我能够理解C语言在这一块做的很不好。
2、所谓脏数据应该是不能预知的,每次程序运行由于分配的地址不同,基本没有相同的可能的数据。那么每次运行程序的时候,这个脏数据应该是不同的(碰上相同的几率应该极小)。
3、同第2.
刚刚看到你的回复后,我第3次关闭了虚拟机,关闭电脑,做到了硬件重启,第4次尝试运行这段代码,得到的结果和前面是一致的。数组值输出得到的还是:@I love Fis
我没有别的意思,只是纯粹的好奇,为什么前面的脏数据一直是一个@,然后紧接着一个结束符‘\0'。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-7-9 12:55:13 | 显示全部楼层
顶级太阳 发表于 2022-7-9 09:23
1、我用%s打印str字符串纯粹是为了好奇在没有初始值的情况下会发生什么,并没有感觉数组变大了。我能够理 ...

一直是@,这与不同系统的内存管理有关,也许系统给整个程序分配内存时已经进行了某种初始化。正如我在win10系统下运行,前面的乱码是“烫烫烫烫”一样。
另外,在实际测试之前,也不能断定脏数据就是 @加一个‘\0’,因为脏数据里解释成字符的未必全是可打印字符,有的被解释成非打印字符(如控制字符)你是看不出来的,严谨一点的方法就是把数组里的每个元素单独打印,就会知道原本的 '\0' 前到底有多少字节
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-17 07:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表