你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

问一个C语言上的问题

[复制链接]
NapoleonWang 提问时间:2017-4-11 11:15 /
悬赏5ST金币已解决
调试程序过程中,遇到了一个问题。如下:
#define  DEFAULT_SE          "000000 "   //有7个字符



char SerialNum[7];  //定义一个数组


strcpy( SerialNum , DEFAULT_SE);  //复制内存中的数据


i =strlen(DEFAULT_SE);
j=strlen(SerialNum);


结果打印出来的:
i=7
j>7(j是一个大于7的数)


我的疑问不确定,大家帮我分析下:
1、宏定义DEFAULT_SE虽然是7个字符,但是后面编译器自动加了一个\0 吗?,那实际上是不是有8个字符长度?
2、由于SerialNum 的定义只有七个字节宽度,导致strcpy(SerialNum, DEFAULT_SE)没有将\0复制过去,也就是SerialNum结尾没有\0,导致计算得j>7呢?


另外,看了一下百度百科对C语言中strcpy的介绍:
C语言标准库函数strcpy,把从src地址开始且含有'\0'结束符的字符串复制到以dest开始的地址空间
也就是说strcpy这个函数是把最后的\0复制过去的,根本原因是我这个地方定义数组内存不够导致的,是这样的吗?


还请各位老师指教。谢谢。

最佳答案

查看完整内容

楼主只说有7个字符(没说7个0),这个没毛病。 潜在的毛病是: 1.strcpy会通过判断‘\0’来遍历DEFUALT_SE,然后把所有的有效字符都复制到SerialNum里面,你没有在这里死机是因为:刚好第7个字符是‘\0’也就不再复制了,虽然这里没死机,但是这是你碰上了,而不是你的业务能力好(反而明显的暴露了你的水平)。这种写法虽然没死机但实际是错误的(如下述)! 2.一般,定义一个字符串,然后使用C库里面的字符串处理函数,比如str ...
收藏 评论14 发布时间:2017-4-11 11:15

举报

14个回答
moyanming2013 回答时间:2017-4-11 11:15:26
本帖最后由 moyanming2013 于 2017-4-11 12:30 编辑
MrJiu 发表于 2017-4-11 11:43
首先,你要去小学进修一下下!!!"000000 "->这只有6个0,不是7个;
其次,字符串很显然是会在后面加\0的 ...

QQ截图20170411121411.jpg
楼主只说有7个字符(没说7个0),这个没毛病。
潜在的毛病是:
1.strcpy会通过判断‘\0’来遍历DEFUALT_SE,然后把所有的有效字符都复制到SerialNum里面,你没有在这里死机是因为:刚好第7个字符是‘\0’也就不再复制了,虽然这里没死机,但是这是你碰上了,而不是你的业务能力好(反而明显的暴露了你的水平)。这种写法虽然没死机但实际是错误的(如下述)!
2.一般,定义一个字符串,然后使用C库里面的字符串处理函数,比如strlen、strcpy等等,都需要确保最后必须有个‘\0’,C库函数都是用‘\0’来判断遍历的结束的,所以,对于SerialNum来说执行完strcpy后,它里面没有‘\0’,导致的结果是后续对SerialNum用C库函数都会有死机的风险,而且风险巨大。编译器对显示字符串都会在其最后自动添加一个‘\0’。
3.上述C库是老库,你可以用诸如strncpy等带有‘n’的保险的c库函数,在一些时候它可以给你“我是对的”的假象,其实你是碰上了,但实际是错误的。再者,你可以自己写一些类似的函数而不用关注‘\0’,但必须指定真实的长度,比如针对SerialNum,真实长度是7,必须时刻跟着长度!这个时候,往往把它做成一个结构体,一个数组成员str,一个实际长度成员strLen。此时就可以不用特殊的‘\0’了(节省了1个字节),因为我们自己处理。

MrJiu 回答时间:2017-4-11 11:43:26
首先,你要去小学进修一下下!!!"000000 "->这只有6个0,不是7个;
其次,字符串很显然是会在后面加\0的,否则就不叫字符串了;
最后,至于你说的j打印出来的值是大于7的...我觉得不太可能,因为SerialNum的内存是够存储的!!!当然,除非你把"000000 "6个0变成7个0,这样SerialNum就不够存储了!!但是,strcpy和strlen都是以检测\0作为检测结束符,所以,有可能数组溢出,进而导致跑飞!!!!
NapoleonWang 回答时间:2017-4-11 13:10:16
MrJiu 发表于 2017-4-11 11:43
首先,你要去小学进修一下下!!!"000000 "->这只有6个0,不是7个;
其次,字符串很显然是会在后面加\0的 ...

首先确实是六个0,后面加个空格。一看到你说的前一句,下面的就懒得看了。还是看看楼下的兄弟解答吧。;olo
NapoleonWang 回答时间:2017-4-11 13:29:25
  bu neng da zi,  bu neng  hui fu .shen me qing kuang .  wo xiang hui lou shang  de .
NapoleonWang 回答时间:2017-4-11 13:46:03
moyanming2013 发表于 2017-4-11 12:26
楼主只说有7个字符(没说7个0),这个没毛病。
潜在的毛病是:
1.strcpy会通过判断‘\0’来遍历DEFUALT_S ...

wei  shen  me  bu  neng  da zi ......
MrJiu 回答时间:2017-4-11 13:48:53
moyanming2013 发表于 2017-4-11 12:26
楼主只说有7个字符(没说7个0),这个没毛病。
潜在的毛病是:
1.strcpy会通过判断‘\0’来遍历DEFUALT_S ...

注意楼主的下面言论,第7个不是指\0的,然后楼主补充了一下,后面有个空格...说实话这个空格完全就是考虑人的眼神啊,
MrJiu 回答时间:2017-4-11 13:51:59
NapoleonWang 发表于 2017-4-11 13:10
首先确实是六个0,后面加个空格。一看到你说的前一句,下面的就懒得看了。还是看看楼下的兄弟解答吧。;ol ...

首先,你这个问题完全就是误导人啊!!!!鬼会注意别人的空格!!!
其次,我下面的解释恰好是完全正确的,注意我说了这么一句话:至于你说的j打印出来的值是大于7的...我觉得不太可能,这是基于我没有注意到空格的前提得出的结论....如果是由空格,那j的值就是一个看情况,未知的值,因为完全取决于这个只指针自加的时候,什么时候指到的值是\0就结束!!!
moyanming2013 回答时间:2017-4-11 15:12:29
MrJiu 发表于 2017-4-11 13:48
注意楼主的下面言论,第7个不是指\0的,然后楼主补充了一下,后面有个空格...说实话这个空格完全就是考虑 ...

我当然看到有个空格啦,我看你的回复你是没看到这个空格。
还是我说的,7个字符没错啊:6个0+1个空格=7个字符,你说楼主(红框部分):
QQ截图20170411150422.jpg
楼主没说有7个0啊!再说了,楼主说7个字符也没错啊(是你少看了1个空格)。要我说不要在眼神上下文章,这个眼神完全不是重点,重点是没看清还胡说。
哎~~再再说了,你作为版主怎么能这么说楼主呢,要是大家什么都会,还要论坛干什么,还要工作干什么,去大街上等风把钱刮过来就行了。不能以为自己是版主就开始卖弄,更不能侮辱别人!子曰“三人行,必有我师焉”。
请问你只发过3个主题帖,怎么当上的版主?
QQ截图20170411150620.jpg
moyanming2013 回答时间:2017-4-11 15:34:59
我3楼(https://www.stmcu.org.cn/module/ ... amp;fromuid=3089512)讲了那么多理论还没看明白啊,我还是针对你的问题通俗点回答你吧:
1.编译器会自动给显示字符串加1个字符‘\0’,但实际上字符长度是7。
注意:编译器自动加个字符,也会自动管理这里面的内存分配。这和字符数组不同,字符数组的大小是确定的,内存分配也是确定的,故要给出1个空余字节来存放‘\0’,否则参考我回复的3楼里面的第3条。
2.strcpy什么都不知道,只知道复制内存,遇到‘\0’就停止。同时为了保证C字符串的完整性,会把这个‘\0’添加到(或复制到)目的地址。此时,因为SerialNum的大小是7,所以往第7个下标写‘\0’时会死机,但这里没死机,没死机是个意外,死机才是正常的,我分析可能是由于字符对齐、编译器优化等等才会没死机,致使第7个内存位置是可读写的位置。因为SerialNum的大小是7,此时该数组里面没有‘\0’,当使用C库函数strlen(SerialNum)时,至少在前7个字节中找不到结束标识‘\0’,故j>=7,没死机你很万幸,但完全是错误的!因为strlen会继续找下去直到碰到‘\0’才停止,你想想会如何呢?会碰到不可读的内存,此时会出现硬件错误!

点评

解释正确,这个确实是初学者容易犯的错误!  发表于 2017-4-14 07:05
NapoleonWang 回答时间:2017-4-11 15:51:10
moyanming2013 发表于 2017-4-11 15:34
我3楼(https://www.stmcu.org.cn/module/forum/forum.php?mod=redirect&goto=findpost&ptid=611439&pid=225230 ...

懂了!
MrJiu 回答时间:2017-4-11 16:41:53
本帖最后由 MrJiu 于 2017-4-11 16:44 编辑
moyanming2013 发表于 2017-4-11 15:12
我当然看到有个空格啦,我看你的回复你是没看到这个空格。
还是我说的,7个字符没错啊:6个0+1个空格=7个 ...

首先,这是网页,看不清楚是很容易的,这并不是胡说,是确实很容易漏;
其次,作为提问者,应该尽量学会如何提问,减少不必要的疑问;
最后,我整个回答没有啥任何毛病,当然去小学进修,这难道不是幽默之类的吗,难道现在的人看到这样的就想到语言暴力了??
最后的最后,版主是坛主邀请我来的哦!!!!而且给我分配的任务是:打赏认可的答案,和封掉打广告和骂人的账户....至于发帖和回答并没有要求!!!当然,我也尽量在回答自己可以回答的!!!!至于发帖,一直在策划中,而且,我本身非常反感那种毫无经验、思想的分享,上来就是一些代码的帖子,这种分享,除了真正需要的,对于其他人,毫无帮助!!!!
moyanming2013 回答时间:2017-4-11 17:07:22
MrJiu 发表于 2017-4-11 16:41
首先,这是网页,看不清楚是很容易的,这并不是胡说,是确实很容易漏;
其次,作为提问者,应该尽量学会如 ...

恩,误解了你当版主的职责了。支持剔除“无营养”的赚金币的帖子。
NapoleonWang 回答时间:2017-4-12 22:44:12
MrJiu 发表于 2017-4-11 11:43
首先,你要去小学进修一下下!!!"000000 "->这只有6个0,不是7个;
其次,字符串很显然是会在后面加\0的 ...

为了尽量还原我遇到问题时的场景,这个最后有个空格的宏定义是我直接在项目里面复制过来的,为了消除坛友的疑惑,特意在后面加了个注释//7个字符.怪我喽..

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版