C语言最佳实践
上QQ阅读APP看书,第一时间看更新

1.3.2 其他常见的编码风格

除了Linux内核的编码风格,流传较为广泛的还有GNU的C语言编码风格(后文简称GNU编码风格),以及Win32编码风格等。

知识点:GNU

GNU是GNU’s Not UNIX的递归缩写,它是由自由软件基金会(Free Software Foundation,FSF)于20世纪80年代发起的一个重要的自由软件项目。GNU项目的目标是开发一个自由的UNIX变种HURD。尽管HURD的开发处在停滞状态,但GNU项目开发和维护着许多高质量的基础软件和工具,其中包括基础库(Glibc)、编译器(GCC)、编辑器(Emacs)以及各类命令行工具。这些软件至今仍然在我们的软件世界中扮演着非常重要的角色。GNU项目的大部分软件是使用C语言开发的。

GNU编码风格同样要求每行代码的字符不能超过80个,但在排版上和Linux内核的编码风格有较大的区别,尤其在缩进、空格和大括号的位置方面区别较大。比如下面这段使用GNU编码风格的代码:

int
lots_of_args (int x, long y, short z,
              double a_double, float a_float)
{
  int haha = 0;
 
  if (x < foo (y, z))
      haha = bar[4] + 5;
  else
  {
    while (z)
      {
        haha += foo (z, z);
        z--;
      }
    return ++x + bar ();
  }
 
  return haha;
}

如果按照Linux内核的编码风格,则应修改为如下形式:

int lots_of_args(int x, long y, short z, double a_double, float a_float)
{
        int haha = 0;
 
        if (x < foo(y, z)) {
                haha = bar[4] + 5;
        } else {
                while (z) {
                        haha += foo(z, z);
                        z--;
                }
 
                haha = ++x + bar();
        }
 
        return haha;
}

除了排版、注释、语法约定、命名等属于代码可读性范畴的内容,GNU的编码风格还包括如下方面的一些规定。

(1)系统可移植性:规定了如何处理跨操作系统的可移植性。

(2)处理器可移植性:规定了如何应对不同种类的处理器或处理器架构。

(3)系统函数:规定了如何应对不同平台在标准函数库上的差异。

(4)规定了国际化、字符集、引号的使用以及mmap函数的使用等。

这些规定是经验性约定,属于代码可维护性的范畴。

Win32编码风格并不像GNU编码风格或者Linux内核的编码风格那样存在一个在线可查阅的版本,而是散见于Win32头文件以及各种示例程序中。我们可以将Win32编码风格理解成匈牙利命名法的集大成者。

在开源项目MiniGUI中,由于其API模仿Win32而来,因此其编码风格极具匈牙利命名法风格。下面是MiniGUI中ShowWindow()函数的实现代码。

/*
 ** This function shows window in behavious by specified iCmdShow.
 */
BOOL GUIAPI ShowWindow (HWND hWnd, int iCmdShow)
{
    MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
 
    if (IsMainWindow (hWnd)) {
        ...
    }
    else {
        PCONTROL pControl;
 
        pControl = (PCONTROL)hWnd;
 
        if (pControl->dwExStyle & WS_EX_CTRLASMAINWIN) {
            ...
        }
        else {
            switch (iCmdShow) {
            case SW_HIDE:
                if (pControl->dwStyle & WS_VISIBLE) {
 
                    pControl->dwStyle &= ~WS_VISIBLE;
                    InvalidateRect ((HWND)(pControl->pParent),
                            (RECT*)(&pControl->left), TRUE);
                }
                break;
            ...
            }
        }
 
        if (iCmdShow == SW_HIDE && pControl->pParent->active == pControl) {
            SendNotifyMessage (hWnd, MSG_KILLFOCUS, 0, 0);
            pControl->pParent->active = NULL;
        }
    }
 
    SendNotifyMessage (hWnd, MSG_SHOWWINDOW, (WPARAM)iCmdShow, 0);
 
    return TRUE;
}

从上述代码中可以看出,Win32编码风格的典型特征如下。

使用匈牙利命名法命名变量,如上述代码中的iCmdShowpControl,前者表示整型变量,后者表示指针。

使用匈牙利命名法命名函数,如上述代码中的SendNotifyMessage()InvalidateRect()

较多地使用了类型定义,如上述代码中的HWNDBOOLWPARAMRECT等;其中的RECT是一个结构体,它定义了一个矩形的左上角和右下角两个顶点的坐标。

值得一提的是,上面的代码对字符数超过80的行做了绕行处理,但Win32编码风格对这一点并不作硬性限制。毕竟Windows平台为开发者提供了图形化的集成开发环境,每行字符超过80个并不会给程序员带来很大的困扰。另外,由于Win32 API和变量名通常较长,因此一行代码很容易超过80个字符。

随着Windows平台上的主流编程语言从C转为C++,而后又转为C#,现在使用Win32编码风格的C代码已经相对少见了。