调试程序过程中,遇到了一个问题。如下: #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库里面的字符串处理函数,比如strlen、strcpy等等,都需要确保最后必须有个‘\0’,C库函数都是用‘\0’来判断遍历的结束的,所以,对于SerialNum来说执行完strcpy后,它里面没有‘\0’,导致的结果是后续对SerialNum用C库函数都会有死机的风险,而且风险巨大。编译器对显示字符串都会在其最后自动添加一个‘\0’。
3.上述C库是老库,你可以用诸如strncpy等带有‘n’的保险的c库函数,在一些时候它可以给你“我是对的”的假象,其实你是碰上了,但实际是错误的。再者,你可以自己写一些类似的函数而不用关注‘\0’,但必须指定真实的长度,比如针对SerialNum,真实长度是7,必须时刻跟着长度!这个时候,往往把它做成一个结构体,一个数组成员str,一个实际长度成员strLen。此时就可以不用特殊的‘\0’了(节省了1个字节),因为我们自己处理。
其次,字符串很显然是会在后面加\0的,否则就不叫字符串了;
最后,至于你说的j打印出来的值是大于7的...我觉得不太可能,因为SerialNum的内存是够存储的!!!当然,除非你把"000000 "6个0变成7个0,这样SerialNum就不够存储了!!但是,strcpy和strlen都是以检测\0作为检测结束符,所以,有可能数组溢出,进而导致跑飞!!!!
首先确实是六个0,后面加个空格。一看到你说的前一句,下面的就懒得看了。还是看看楼下的兄弟解答吧。;olo
wei shen me bu neng da zi ......
注意楼主的下面言论,第7个不是指\0的,然后楼主补充了一下,后面有个空格...说实话这个空格完全就是考虑人的眼神啊,
首先,你这个问题完全就是误导人啊!!!!鬼会注意别人的空格!!!
其次,我下面的解释恰好是完全正确的,注意我说了这么一句话:至于你说的j打印出来的值是大于7的...我觉得不太可能,这是基于我没有注意到空格的前提得出的结论....如果是由空格,那j的值就是一个看情况,未知的值,因为完全取决于这个只指针自加的时候,什么时候指到的值是\0就结束!!!
我当然看到有个空格啦,我看你的回复你是没看到这个空格。
还是我说的,7个字符没错啊:6个0+1个空格=7个字符,你说楼主(红框部分):
楼主没说有7个0啊!再说了,楼主说7个字符也没错啊(是你少看了1个空格)。要我说不要在眼神上下文章,这个眼神完全不是重点,重点是没看清还胡说。
哎~~再再说了,你作为版主怎么能这么说楼主呢,要是大家什么都会,还要论坛干什么,还要工作干什么,去大街上等风把钱刮过来就行了。不能以为自己是版主就开始卖弄,更不能侮辱别人!子曰“三人行,必有我师焉”。
请问你只发过3个主题帖,怎么当上的版主?
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’才停止,你想想会如何呢?会碰到不可读的内存,此时会出现硬件错误!
点评
懂了!
首先,这是网页,看不清楚是很容易的,这并不是胡说,是确实很容易漏;
其次,作为提问者,应该尽量学会如何提问,减少不必要的疑问;
最后,我整个回答没有啥任何毛病,当然去小学进修,这难道不是幽默之类的吗,难道现在的人看到这样的就想到语言暴力了??
最后的最后,版主是坛主邀请我来的哦!!!!而且给我分配的任务是:打赏认可的答案,和封掉打广告和骂人的账户....至于发帖和回答并没有要求!!!当然,我也尽量在回答自己可以回答的!!!!至于发帖,一直在策划中,而且,我本身非常反感那种毫无经验、思想的分享,上来就是一些代码的帖子,这种分享,除了真正需要的,对于其他人,毫无帮助!!!!
恩,误解了你当版主的职责了。支持剔除“无营养”的赚金币的帖子。
为了尽量还原我遇到问题时的场景,这个最后有个空格的宏定义是我直接在项目里面复制过来的,为了消除坛友的疑惑,特意在后面加了个注释//7个字符.怪我喽..