当前位置:  开发笔记 > 编程语言 > 正文

我应该如何在C中构建复杂的项目?

如何解决《我应该如何在C中构建复杂的项目?》经验,为你挑选了4个好方法。

我只有初学者级别的C技能,并想知道是否有任何事实上的"标准"来构建C中有点复杂的应用程序.甚至基于GUI的应用程序.

我一直在Java和PHP中使用OO范例,现在我想学习C我害怕我可能以错误的方式构建我的应用程序.我无法遵循哪些指导方针,使用程序语言实现模块化,解耦和干燥.

你有任何建议吗?我找不到C的任何应用程序框架,即使我不使用框架,我总是通过浏览他们的代码找到好的想法.



1> mouviciel..:

关键是模块化.这更容易设计,实现,编译和维护.

识别应用中的模块,例如OO应用中的类.

每个模块的独立接口和实现,仅在接口中放入其他模块所需的接口.请记住,C中没有命名空间,因此您必须使接口中的所有内容都是唯一的(例如,使用前缀).

在实现中隐藏全局变量并使用访问器函数进行读/写.

不要考虑继承,而是考虑构成.作为一般规则,不要试图在C中模仿C++,这将非常难以阅读和维护.

如果您有时间学习,请查看Ada应用程序的结构,包括强制package(模块接口)和package body(模块实现).

这是为了编码.

为了维护(记住你编码一次,但你保持了几次)我建议记录你的代码; Doxygen对我来说是一个不错的选择.我建议还要建立一个强大的回归测试套件,它允许你重构.



2> j_random_hac..:

这是一种常见的误解,即OO技术无法应用于C.大多数情况下 - 只是它们比具有专用于工作的语法的语言稍微笨拙.

强大的系统设计的基础之一是封装接口背后的实现. FILE*和与它(工作功能fopen(),fread()等)是如何封装可以在C被施加到接口建立一个很好的例子.(当然,由于C缺少访问说明符,你不能强制执行,没有人偷看struct FILE,但只有受虐狂会这样做.)

如有必要,可以使用函数指针表在C中获得多态行为.是的,语法很丑,但效果与虚函数相同:

struct IAnimal {
    int (*eat)(int food);
    int (*sleep)(int secs);
};

/* "Subclass"/"implement" IAnimal, relying on C's guaranteed equivalence
 * of memory layouts */
struct Cat {
    struct IAnimal _base;
    int (*meow)(void);
};

int cat_eat(int food) { ... }
int cat_sleep(int secs) { ... }
int cat_meow(void) { ... }

/* "Constructor" */
struct Cat* CreateACat(void) {
    struct Cat* x = (Cat*) malloc(sizeof (struct Cat));
    x->_base.eat = cat_eat;
    x->_base.sleep = cat_sleep;
    x->meow = cat_meow;
}

struct IAnimal* pa = CreateACat();
pa->eat(42);                       /* Calls cat_eat() */

((struct Cat*) pa)->meow();        /* "Downcast" */


@mouviciel:垃圾!大多数C编码员都理解函数指针(或者至少他们应该这样),并且除此之外没有任何其他内容真正发生.至少在Windows上,设备驱动程序和COM对象都以这种方式提供其功能.
一个纯粹的C编码器会丢失阅读这段代码......
我的观点不是关于不称职,而是关于不必要的并发症.函数指针对于C编码器是常见的(例如,回调),而继承则不是.我更喜欢C语言编写的C++编码器使用它来学习C而不是构建伪C++类.也就是说,在某些情况下,您的方法可能很有用.
实际上你甚至可以使用C++ pimpl习语来模拟*访问说明符.如果某个类型的*private*成员被封装在仅在实现中可见的类型(也就是".c文件")中,那么界面的用户将很难更改它们(当然,他们可以写垃圾)到pimpl指针,如果他们想故意**你**,但你可以在C++中做同样的事情).
Downvoter:关注评论?

3> Mike Dunlave..:

所有好的答案.

我只会添加"最小化数据结构".这甚至可能会在C更容易,因为如果C++是"带类的C",OOP正试图鼓励你们采取一切名词/动词在你的头上,并把它变成一个类/方法.这可能非常浪费.

例如,假设您在某个时间点有一系列温度读数,并且您希望在Windows中将它们显示为折线图.Windows有一条PAINT消息,当你收到它时,你可以循环执行LineTo函数的数组,在你将数据转换为像素坐标时缩放数据.

我所看到的完全过很多次,由于图由点和线,人们将建立一个数据结构,其中包括点对象和线对象,每一个都能够DrawMyself的,然后作出这样的执着,从理论上说是是某种"更有效",或者他们可能,只是可能,必须能够将鼠标指向图表的零件和数字显示的数据,所以他们建立方法引入的对象来处理了,并且,当然,涉及创建和删除更多对象.

因此,您最终会得到大量的代码,这些代码非常易读,而且仅花费90%的时间来管理对象.

所有这些都是以"良好的编程实践"和"效率"的名义完成的.

至少在C中,简单,有效的方式将更加明显,并且建造金字塔的诱惑力不那么强烈.



4> 小智..:

在GNU编码标准已经发展了几十年.阅读它们是个好主意,即使你不遵循它们.考虑到它们中提出的要点,可以为您构建自己的代码提供更坚实的基础.


不是每个人都喜欢它们,来自http://lxr.linux.no/linux+v2.6.29/Documentation/CodingStyle:"首先,我建议打印出GNU编码标准的副本,而不是阅读它.他们,这是一个伟大的象征性姿态".多年来我没有读过它们,但是Linus有一些有效的反对意见.
推荐阅读
php
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有