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

纯C(非C++)的编码标准

如何解决《纯C(非C++)的编码标准》经验,为你挑选了4个好方法。

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

纯C的设计流程和编码标准是什么?

我熟悉面向对象的编程,设计和最佳实践.我只是在像C这样的非面向对象语言上有点不知所措.每个变量和函数似乎都是全局的.这让我感觉真的很乱.



1> 小智..:

您可能有兴趣查看我不久前问过的类似问题的答案.此外,如果您对C风格指南感兴趣,您可能需要查看此页面,因为它是C(和C++)样式指南的存储库.如果你想好笑,请看看NASA C风格指南.特别是,看看大量的评论......你会知道我在谈论哪一个.请不要写这样的评论.

我个人推荐使用Indian Hill C Style Guide进行一些修改.此外,如果您在使用C语言设计大型程序时遇到问题,则可能需要购买" C接口和实现 "一书.


+1因为链接到包含多个C标准链接的网页.

2> 小智..:

老实说,我认为StackOverflow上的任何答案都不会教你如何设计和编写结构良好的C程序.你需要阅读一本好书,显而易见的是Kernighan和Ritchie 编写的The C Programming Language.


K&R在设计流程和编码标准方面没有太多话要说。这是对C的很好的介绍。

3> paercebal..:

我没有C的专业经验(仅限C++),因此不要过于认真地对待我的建议,技巧和提示,因为它们是"面向对象的".

几乎是对象C?

可以轻松地模拟基本类似对象的功能:

在标题中,forward声明你的类型,typedef它,并声明"方法".例如:

/* MyString.h */

#include 

/* 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 
#include 

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) ;
}

避免使用非const全局变量

这包括"静态"变量(不是静态函数).

全局非const变量几乎总是一个坏主意(例如,参见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 ! */

未初始化的变量是导致痛苦的错误的原因.

了解所有C API

K&R中描述的C API函数列表非常小.你会在20分钟内阅读整个清单.你必须知道这些功能.

想要一些经验吗?

重写C API.例如,尝试编写自己的string.h函数版本,以了解它是如何完成的.



4> T.E.D...:

您可以通过将其声明为"静态"来使函数或对象的作用域位于其源文件的本地.这有点帮助.

否则,我看到的避免命名空间冲突的典型习惯是在名称上放置某种设施标识符.例如,foo.c中的所有内容都可能被命名为foo_*

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有