首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >纯C语言的编码标准(不是C++)

纯C语言的编码标准(不是C++)
EN

Stack Overflow用户
提问于 2009-08-11 19:39:17
回答 10查看 42.7K关注 0票数 39

我来自java背景(来自我的CS课程)和一个学期的C++。我刚刚为我的Co-Op完成了一个纯C语言的OpenCV项目,所以我问这个问题有点晚了。

纯C语言的设计过程和编码标准是什么?

我熟悉面向对象编程、设计和最佳实践。我只是对像C这样的非面向对象语言有点迷惑,每个变量和函数似乎都是全局的。这让我觉得它真的一团糟。

EN

回答 10

Stack Overflow用户

发布于 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这本书。

票数 35
EN

Stack Overflow用户

发布于 2009-08-11 19:54:43

老实说,我不认为StackOverflow上的许多答案会教你如何设计和编写结构良好的C程序。你需要读一本好书,最明显的一本书是Kernighan & Ritchie的The C Programming Language

票数 15
EN

Stack Overflow用户

发布于 2009-08-11 21:13:40

我没有C的专业经验(只在C++上),所以不要把我的建议、技巧和技巧看得太重,因为它们是“面向对象的”。

几乎是对象C?

可以很容易地模拟基本的类似对象的功能:

在头文件中,转发声明你的类型,定义它的类型,并声明“方法”。例如:

代码语言:javascript
复制
/* 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式的想法。

在源文件中,定义您的类型,并定义函数:

代码语言:javascript
复制
/* 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源代码中声明它们是静态的。这样,它们在外面就看不见了:

代码语言:javascript
复制
static void doSomethingPrivate()
{
   /* etc. */
}

static int g_iMyPrivateCounter = 0 ;

如果你想继承,那你就大错特错了。如果您认为C中的所有东西都是全局的,包括变量,那么在尝试考虑如何模拟继承之前,您应该获得更多的C经验。

其他。提示

避免多个代码路径。

例如,多个回报是有风险的。例如:

代码语言:javascript
复制
void doSomething(int i)
{
   void * p = malloc(25) ;

   if(i > 0)
   {
      /* this will leak memory ! */
      return ;
   }

   free(p) ;
}

避免非常量全局变量

这包括“静态”变量(不是静态函数)。

全局非常量变量几乎总是一个糟糕的想法(例如,参见C API strtok了解一个糟糕的函数示例),如果生成多线程安全的代码,处理它们将是一件痛苦的事情。

避免名称冲突

为你的函数和你的定义选择一个“命名空间”。这可能是:

代码语言:javascript
复制
#define GROOVY_LIB_x_MY_CONST_INT 42

void GroovyLib_dosomething() ;

注意定义

定义在C中是无法避免的,但它们可能会有副作用!

代码语言:javascript
复制
#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 !!! */
}

初始化你的变量

避免在未初始化变量的情况下声明变量:

代码语言:javascript
复制
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函数,看看它是如何完成的。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1262459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档