我来自java背景(来自我的CS课程)和一个学期的C++。我刚刚为我的Co-Op完成了一个纯C语言的OpenCV项目,所以我问这个问题有点晚了。
纯C语言的设计过程和编码标准是什么?
我熟悉面向对象编程、设计和最佳实践。我只是对像C这样的非面向对象语言有点迷惑,每个变量和函数似乎都是全局的。这让我觉得它真的一团糟。
发布于 2009-08-11 21:20:49
你可能有兴趣看看我不久前问过的一个similar question的答案。此外,如果你对C风格的指南感兴趣,你可能想看看this page,因为它是C(和C++)风格指南的存储库。如果你有心情来一次good look ,请看看NASA C Style Guide。尤其是,看看大量的评论...你就知道我说的是哪一个了。请不要这样写评论。
我个人推荐带一些修改的Indian Hill C Style Guide。此外,如果您在用C语言设计大型程序时遇到困难,您可能需要购买C Interfaces and Implementations这本书。
发布于 2009-08-11 19:54:43
老实说,我不认为StackOverflow上的许多答案会教你如何设计和编写结构良好的C程序。你需要读一本好书,最明显的一本书是Kernighan & Ritchie的The C Programming Language。
发布于 2009-08-11 21:13:40
我没有C的专业经验(只在C++上),所以不要把我的建议、技巧和技巧看得太重,因为它们是“面向对象的”。
几乎是对象C?
可以很容易地模拟基本的类似对象的功能:
在头文件中,转发声明你的类型,定义它的类型,并声明“方法”。例如:
/* MyString.h */
#include <string.h>
/* Forward declaration */
struct StructMyString ;
/* Typedef of forward-declaration (note: Not possible in C++) */
typedef struct StructMyString MyString ;
MyString * MyString_new() ;
MyString * MyString_create(const char * p_pString) ;
void MyString_delete(MyString * p_pThis) ;
size_t MyString_length(const MyString * p_pThis) ;
MyString * MyString_copy(MyString * p_pThis, const MyString * p_pSource) ;
MyString * MyString_concat(MyString * p_pThis, const MyString * p_pSource) ;
const char * MyString_get_c_string(const MyString * p_pThis) ;
MyString * MyString_copy_c_string(MyString * p_pThis, const char * p_pSource) ;
MyString * MyString_concat_c_string(MyString * p_pThis, const char * p_pSource) ;
你会看到每个函数都有前缀。我选择"struct“的名称,以确保不会与其他代码发生冲突。
您还会看到,我使用了"p_pThis“来保持OO式的想法。
在源文件中,定义您的类型,并定义函数:
/* MyString.c */
#include "MyString.h"
#include <string.h>
#include <stdlib.h>
struct StructMyString
{
char * m_pString ;
size_t m_iSize ;
} ;
MyString * MyString_new()
{
MyString * pMyString = malloc(sizeof(MyString)) ;
pMyString->m_iSize = 0 ;
pMyString->m_pString = malloc((pMyString->m_iSize + 1) * sizeof(char)) ;
pMyString->m_pString[0] = 0 ;
return pMyString ;
}
/* etc. */
如果您想要“私有”函数(或私有全局变量),请在C源代码中声明它们是静态的。这样,它们在外面就看不见了:
static void doSomethingPrivate()
{
/* etc. */
}
static int g_iMyPrivateCounter = 0 ;
如果你想继承,那你就大错特错了。如果您认为C中的所有东西都是全局的,包括变量,那么在尝试考虑如何模拟继承之前,您应该获得更多的C经验。
其他。提示
避免多个代码路径。
例如,多个回报是有风险的。例如:
void doSomething(int i)
{
void * p = malloc(25) ;
if(i > 0)
{
/* this will leak memory ! */
return ;
}
free(p) ;
}
避免非常量全局变量
这包括“静态”变量(不是静态函数)。
全局非常量变量几乎总是一个糟糕的想法(例如,参见C API strtok了解一个糟糕的函数示例),如果生成多线程安全的代码,处理它们将是一件痛苦的事情。
避免名称冲突
为你的函数和你的定义选择一个“命名空间”。这可能是:
#define GROOVY_LIB_x_MY_CONST_INT 42
void GroovyLib_dosomething() ;
注意定义
定义在C中是无法避免的,但它们可能会有副作用!
#define MAX(a, b) (a > b) ? (a) : (b)
void doSomething()
{
int i = 0, j = 1, k ;
k = MAX(i, j) ; /* now, k == 1, i == 0 and j == 1 */
k = MAX(i, j++) ; /* now, k == 2, i == 0 and j == 3, NOT 2, and NOT 1 !!! */
}
初始化你的变量
避免在未初始化变量的情况下声明变量:
int i = 42 ; /* now i = 42 */
int j ; /* now j can have any value */
double k ; /* now f can have any value, including invalid ones ! */
未初始化的变量是导致痛苦的bug的原因。
了解所有的C API
在K&R中描述的C API函数列表非常小。你将在20分钟内读完整个清单。您必须了解这些函数。
想要一些经验吗?
重写C API。例如,尝试编写您自己版本的string.h .h函数,看看它是如何完成的。
https://stackoverflow.com/questions/1262459
复制相似问题