游戏开发论坛

 找回密码
 立即注册
搜索
查看: 5477|回复: 15

[原创]你真的了解C吗?

[复制链接]

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
发表于 2004-6-9 09:52:00 | 显示全部楼层 |阅读模式
俺用C的时间比用C++长多了,现在C++的代码中,也不经意的会透露出一些C的风格。记得有位高人说过:好的C代码一般都不是好的C++代码。所以我的C++代码看起来并不是很舒服。

大家学编程语言应该有一大部分人看过潭浩强的C语言的书吧,那本书写得很好,但是却写得很片面,没有让人了解到C的一些更efficient的特性。下面来讲一些:

大家是不是经常碰到这种情况,有一个指针,指向一个数组,然后把这个指针传给一个函数处理,那么这个函数在处理这个指针的时候,怎么能知道数组的元素呢?比如说,你传一个坐标指针给一个函数,这个函数如何知道这个指针会有两个元素(x,y)呢?
一般的写法是:
char buf[255];
char *p = buf;
(void)process_buf(p);
这里process_buf的定义是void process_buf(char *p);
无论你定义成void process_buf(char newbuf[]);
或者是void process_buf(char newbuf[255]);
实际上传进来的就是一个指针,你可以任意操作。
但是你的函数这个时候就不好办了,不知道这个指针究竟能操作到什么地方。
或者传进来的是个垃圾指针,函数都不知道。
所以在C99标准里面,比较efficient的声明process_buf是:
void process_buf(char newbuf[static 255]);
(不要用VC去试,那个不支持C99,GCC对C99支持得最好,可以用-std=c99编译选项)
这个声明的意思就是保证newbuf这个指针最少有255个元素。
==============================================
另外,是否经常碰到这种情况,有一个函数叫calXY(pos_t *xy);
pos_t的定义位:
typedef struct {int x; int y;} pos_t;
然后你已经计算出x和y的值了,但是为了传给calXY函数,又不得不再声明一个
pos_t pos;
pos.x = my_x;
pos.y = my_y;
之类的?其实比较好的做法是不用这样,而是直接:
calXY( (pos_t*){my_x, my_y} );
==============================================
当碰到要计算一个struct里面的某个成员的offset时,你又会怎么做呢?
比如有个结构:
struct my_struct {
    int a;
    int b;
};
当你想获得b在my_struct这个结构中的offset的时候,你会怎么做呢?是不是
struct my_struct test;
int offset = &(test.b) - &test; 呢?
这里告诉你个更efficient的做法:
struct my_struct *p;
p = 0;
int offset = &(p->b); 都不需要给p分配内存就可以做到。
==============================================
还有,在编写网络传输的时候,大家是不是碰到过这种情况呢?
要把某人的聊天信息传输过去,那么如何来定制这个结构呢?有些比较愚蠢的办法是:
typedef struct chat_s {
     struct message_header head;
     char msg[255];
} chat_t;
来发聊天消息,因为他们不知道如何定制一个变长的结构体。
有些人会比较聪明,会知道用:
typedef struct chat_s {
    struct message_header head;
    char msg[1];
} chat_t;
这样的结构来保存聊天消息,这样可以更方便的指定变长,但是又是连续内存的结构体。
那么实际上呢,C本身就对这种结构有支持,正确的写法应该是:
typedef struct chat_s {
    struct message_header head;
    char msg[];
} chat_t;
当然,这个特性只有在支持C99的编译器上才能编译通过。
==============================================
还有,对于struct timeval这个结构,大家都知道吧,它里面有两个东西,一个
tv_sec和一个tv_usec,是用来设定时间的,很多时候我们都只需要tv_usec来
表示一个微秒级的时间,而tv_sec常常都是0,比如在select的时候。我们会这样写:
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 30;
select(xx, xx, xx, xx, &tv);
当然,这样写是绝对正确的,但是我们需要更efficient的写法,就是:
select(xx, xx, xx, xx, &( struct timeval ){.tv_usec = 30 });
这样默认的tv_sec会被设置为0,这是一个比较好的初始化方法,不需要memset
也不需要一个个的赋值。
这个也是C99的特性。
==============================================
总而言之,潭浩强老师的书确实写得不错,在他那个年代,C99规范还没出来的时候
他总结得很全,但是随着现在几乎所有的C编译器都开始支持C99,包括一些C++编译
器也开始支持C99规范,我们是不是也应该开始改改我们的一些编程习惯?

201

主题

1437

帖子

1963

积分

金牌会员

Rank: 6Rank: 6

积分
1963
QQ
发表于 2004-6-9 10:07:00 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

54

主题

2917

帖子

3765

积分

论坛元老

Rank: 8Rank: 8

积分
3765
QQ
发表于 2004-6-9 13:24:00 | 显示全部楼层

Re:[原创]你真的了解C吗?

楼主的第一个例题有点类似我以前提过的问题,但是最终无果。
本人非常讲究代码的可移植性,什么类似这个编译器可以那个编译器不行的代码对我而言是不可取的。

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
 楼主| 发表于 2004-6-9 15:37:00 | 显示全部楼层

Re:[原创]你真的了解C吗?

C99以后都会支持的。。。

2

主题

13

帖子

17

积分

新手上路

Rank: 1

积分
17
发表于 2004-6-9 16:26:00 | 显示全部楼层

Re:[原创]你真的了解C吗?

有些技巧,感觉是不安全的做法!

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
 楼主| 发表于 2004-6-9 17:08:00 | 显示全部楼层

Re:[原创]你真的了解C吗?

哪个不安全?

17

主题

177

帖子

177

积分

注册会员

Rank: 2

积分
177
QQ
发表于 2004-6-9 18:49:00 | 显示全部楼层

Re:[原创]你真的了解C吗?

char msg[];???不指定大小.可以吗???VC6.0中好象不行吧..
warning C4200: nonstandard extension used : zero-sized array in struct/union

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
 楼主| 发表于 2004-6-9 21:15:00 | 显示全部楼层

Re:[原创]你真的了解C吗?

这是C99规范的,你用gcc 3.0以上就可以了

121

主题

2029

帖子

2034

积分

金牌会员

Rank: 6Rank: 6

积分
2034
QQ
发表于 2004-6-10 09:09:00 | 显示全部楼层

Re:[原创]你真的了解C吗?

楼主贴子挺好,不过我用VC++很多特性没法用。。。

0

主题

21

帖子

21

积分

注册会员

Rank: 2

积分
21
发表于 2004-6-10 12:30:00 | 显示全部楼层

Re:[原创]你真的了解C吗?

源码的意义在于让某这个项目的所有人看懂、让程序在不同环境正确编译执行。
不是为了符合某某标准,更不是“需要efficient”而去编程序。
这样讲不是说不要接受新东西。
只是说不要过份张显个性,要与你的伙伴达成一致:尊重团体的选择。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-7-1 18:27

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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