社区导航

 

搜索
查看: 3774|回复: 12

[讨论] C语言二维字符数组使用的误区

[复制链接]

594

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

发表于 2012-9-4 10:54 | 显示全部楼层 |阅读模式
误区:在C语言的教学中,发现很多学员老出现这个问题,在定义字符二维数组上,这样定义char buf[][50]={0};后面使用buf[0],buf[1]....总觉得有无穷无尽可以使用。
调试无果:一开始,学员用的没有问题,等项目代码多了,系统变大了,就出现些莫名其妙的问题,调试半天就找不出根源。
原因:实际上就出在这个定义上,这样定义变量就像给系统埋了个定时炸弹,
留下隐患。我们说,定义变量后系统就会开辟一定的内存空间,char buf[][50]={0},这样的定义实际上就只有一个50个字节的内存空间,你若不信,可用sizeof测试下。那为什么还能使用buf[1]呢?系统怎么不报错呢?首先数组是特殊的指针,buf[0]的首地址是buf[0][0],buf[1]的首地址系统就会推算为buf[0][0]+1*50,当你用strcpy(buf[1],"student");系统将会从buf[1]的首地址开始存“student”的数据,但是这些数据是不受保护的,因为buf的合法空间是50个字节,也就是系统会认为后面的空间是闲置的,所以当系统变大,变量使用的多时,内存区不够使用,或刚好使用这块区域,系统读取数据就会混乱,造成系统崩溃,并且这种错误系统报的错经常是不会指向这里的,所以调试就会很困难,再者,VC本身不检查下标的越界,所以就很难找出错误的根源。
此帖出自编程基础论坛
嵌入式培训www.51great.org

回复

使用道具 举报

594

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2012-9-4 10:55 | 显示全部楼层
自己顶下
嵌入式培训www.51great.org

回复

使用道具 举报

1414

TA的帖子

0

TA的资源

纯净的硅(高级)

Rank: 6Rank: 6

发表于 2012-9-4 11:06 | 显示全部楼层
学习了,支持下楼主,多谢

回复

使用道具 举报

7894

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2012-9-4 18:08 | 显示全部楼层
居然不报错,这种狗血的编译器真有它的。。。。。

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

139

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

发表于 2012-9-4 19:57 | 显示全部楼层
char buf[][50]={0};  埋了个定时炸弹,
strcpy(buf[1],"student");  触碰了这个定时炸弹
何时被炸伤看“天意”

言归正传,编码人应该怎样预防潜在BUG放入到程序中呢?

[ 本帖最后由 bill_shi68 于 2012-9-4 20:08 编辑 ]

点评

这个问题很深奥。 为此(我是希望能够写出 高质量 稳健 容易理解 维护 的代码) 所以我关注 极限编程 关注 测试驱动开发 。 有兴趣,一起来吧。  详情 回复 发表于 2012-9-5 22:24

回复

使用道具 举报

139

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

发表于 2012-9-5 10:24 | 显示全部楼层
#include
#include

int main()
{
        char buf_1[][50] = {0};

        char buf_2[][50] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                0, 0, 0, 0};

        printf("size of buf_1:%d\n", sizeof(buf_1));
        printf("size of buf_2:%d\n", sizeof(buf_2));

        strcpy(buf_1[1], "hello");                /* 可以编译通过,但在运行过程中可能破坏其他代码段使用的数据 */
        strcpy(buf_2[1], "hello");

        printf("size of buf_1:%d\n", sizeof(buf_1));                /* 输出50 */
        printf("size of buf_2:%d\n", sizeof(buf_2));                /* 输出100 */

        return 0;
}

/*
char buf[][50] = {...};
这种省略第一维长度的用法本意应该是:当用很多元素初始化二维数组时,让编译器自动算出第一维长度(避免了人为计算的错误)。
当这样定义二维数组时编码者应该只对初始化的数组元素经进行读/写操作,即只对buf_1的1个元素操作,对buf_2的54个元素操作,
当然,熟悉机器运行过程的高人可以不受此限制。
当申请缓冲池、栈时,稳定起见根据事先计算明确给出数组长度,并在使用缓冲池、栈时判别是否越界,如越界应有相应机制处理。

以上仅个人砖头,大家有玉尽量砸过来...........
*/

点评

哥们,你说的第一维长度,这里还有一个很恐怖的现象...... 那就是第一维出现了小数  详情 回复 发表于 2012-9-5 22:28
这个道理其实很简单。 编译器压根不管你三维还是四维,它都把它看做一连串连续字符。 至于二维三维,那是你在用的时候,自己定义的寻址方式。 另一个就是你说的。 如果你没有指定数组的元素个数,那么,编译  详情 回复 发表于 2012-9-5 22:27

回复

使用道具 举报

7894

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2012-9-5 22:24 | 显示全部楼层

回复 5楼 bill_shi68 的帖子

这个问题很深奥。
为此(我是希望能够写出 高质量 稳健 容易理解 维护 的代码)

所以我关注 极限编程 关注 测试驱动开发 。

有兴趣,一起来吧。

点评

刚转到C语言,发现自己的基础还有很多短板,近段正在补习 路漫漫其修远兮...  详情 回复 发表于 2012-9-5 23:55

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

7894

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2012-9-5 22:27 | 显示全部楼层

回复 6楼 bill_shi68 的帖子

这个道理其实很简单。

编译器压根不管你三维还是四维,它都把它看做一连串连续字符。
至于二维三维,那是你在用的时候,自己定义的寻址方式。

另一个就是你说的。
如果你没有指定数组的元素个数,那么,编译时就会以初始化的情况默认元素个数。

于是,天大的乱子就开始了。

任何时候,读写未知的内存单元都是极大的隐患。

不管以数组还是指针异或直接操作地址的形式。

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

7894

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2012-9-5 22:28 | 显示全部楼层

回复 6楼 bill_shi68 的帖子

哥们,你说的第一维长度,这里还有一个很恐怖的现象......

那就是第一维出现了小数

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

7894

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2012-9-5 22:29 | 显示全部楼层
还好,数组的维度的取值只能是整型,不然,那就更好玩了......

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

1万

TA的帖子

33

TA的资源

版主

Rank: 6Rank: 6

发表于 2012-9-5 22:31 | 显示全部楼层
楼主这个问题提得好啊。代码质量也要从细节入手。

回复

使用道具 举报

139

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

发表于 2012-9-5 23:55 | 显示全部楼层

回复 7楼 辛昕 的帖子

刚转到C语言,发现自己的基础还有很多短板,近段正在补习
路漫漫其修远兮...

点评

没事儿,昨天在公车上 看 TDD 突然觉得事情是没完没了的,正如人活着一样。 但只要找到这无穷无尽的循环里的一个改进的起点,就可以从这个点切入,一点一点循着轨迹向前走...... 有点文艺。 简单地说,慢慢来  详情 回复 发表于 2012-9-6 23:12

回复

使用道具 举报

7894

TA的帖子

54

TA的资源

裸片初长成(中级)

Rank: 11Rank: 11Rank: 11Rank: 11

荣誉会员勋章

发表于 2012-9-6 23:12 | 显示全部楼层

回复 12楼 bill_shi68 的帖子

没事儿,昨天在公车上 看 TDD
突然觉得事情是没完没了的,正如人活着一样。
但只要找到这无穷无尽的循环里的一个改进的起点,就可以从这个点切入,一点一点循着轨迹向前走......

有点文艺。
简单地说,慢慢来吧,辛昕在版块里守候着大家。

八年一梦,洗尽铅华,重头再来


回复

使用道具 举报

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

关闭

站长推荐上一条 /5 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-2-20 13:34 , Processed in 0.352570 second(s), 20 queries , Gzip On, MemCache On.

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