我只具备初学者级C技能,并且想知道是否存在任何事实上的“标准”来在C中构建一个稍微复杂的应用程序。甚至包括基于GUI的应用程序。
我一直在Java和PHP中使用OO范例,现在我想学习C语言,恐怕会以错误的方式构造应用程序。我不知所措,要遵循哪些准则以程序语言实现模块化,去耦和干燥。
你有什么建议吗?我找不到C的任何应用程序框架,即使我不使用框架,我也总是通过浏览它们的代码找到不错的主意。
Answers:
关键是模块化。这更易于设计,实现,编译和维护。
如果您有时间学习,请查看Ada应用程序的结构,以及其强制性package
(模块接口)和package body
(模块实现)。
这是用于编码。
为了维护(请记住,您编写了一次代码,但是您维护了几次),我建议记录您的代码。Doxygen对我来说是一个不错的选择。我建议您还建立一个强大的回归测试套件,以便您进行重构。
常见的误解是,OO技术不能在C语言中应用。大多数都可以-只是它们比使用专用于该语法的语言稍微笨拙。
健壮的系统设计的基础之一是在接口后面封装实现。 FILE*
和功能与它(工作fopen()
,fread()
等)是如何封装可以在C被施加到接口建立一个很好的例子。(当然,由于C缺少访问说明符,因此您不能强制A中没有人偷看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" */
所有好的答案。
我只会添加“最小化数据结构”。在C语言中,这甚至可能更容易,因为如果C ++是“带类的C”,那么OOP会试图鼓励您将脑海中的每个名词/动词转换为类/方法。那可能非常浪费。
例如,假设您在某个时间点具有一系列温度读数,并且希望将其显示为Windows中的折线图。Windows收到一条PAINT消息,当您收到消息时,可以遍历执行LineTo函数的数组,并在缩放数据时将其转换为像素坐标。
我完全看过太多次了,由于图表由点和线组成,人们将建立一个由点对象和线对象组成的数据结构,每个对象都具有DrawMyself的功能,然后根据以下理论使其持久化:是某种程度上“更有效率”,或者也许只是必须能够将它们悬停在图表的各个部分上并以数字方式显示数据,因此他们将方法内置到对象中以进行处理,当然,涉及创建和删除更多对象。
因此,您最终将获得大量易于理解的代码,仅花费90%的时间来管理对象。
所有这些都是以“良好的编程习惯”和“效率”的名义完成的。
至少在C语言中,简单,有效的方式会更加明显,而建立金字塔的诱惑力也不会那么强。
在GNU编码标准已经发展了几十年。最好阅读它们,即使您不遵循它们。考虑它们中提出的要点,可以为您如何构建自己的代码提供更牢固的基础。
如果您知道如何用Java或C ++构造代码,则可以对C代码遵循相同的原理。唯一的区别是您不需要编译器,并且需要手动做所有事情。
由于没有包和类,因此需要首先仔细设计模块。最常见的方法是为每个模块创建一个单独的源文件夹。您需要依靠命名约定来区分不同模块之间的代码。例如,所有功能都以模块名称作为前缀。
您不能使用C编写类,但可以轻松实现“抽象数据类型”。您为每种抽象数据类型创建一个.C和.H文件。如果愿意,可以有两个头文件,一个是公共文件,另一个是私有文件。这个想法是所有需要导出的结构,常量和函数都将进入公共头文件。
您的工具也非常重要。C语言有用的工具是lint,它可以帮助您在代码中发现难闻的气味。您可以使用的另一个工具是Doxygen,它可以帮助您生成文档。
我建议您检查任何流行的开源C项目的代码,例如……嗯……Linux内核或Git;看看他们是如何组织的。
复杂应用程序的数字规则:应易于阅读。
为了简化复杂的应用程序,我雇用了 Divide and conquer。