前言

本文章所翻译的C语言代码风格指南全部内容来源于CS50官方英文文档。CS50(计算机科学50)是哈佛大学以及耶鲁大学自2015年起在校园开设的计算机科学在线入门课程,相信不少人都有所耳闻。我觉得其课程所规定的代码风格比较简洁,因此做了一些微小的翻译工作,供大家一起讨论学习。欢迎转载,标明出处即可。

注:CS50代码风格指南原始网址CS50 STYLE GUIDE

C语言代码风格指南

事实上不存在一种唯一正确的代码风格,但是却确实存在大量错误的风格(至少可以说是坏的风格)。CS50要求您遵守以下约定,以便我们能够可靠地分析您的代码样式。同样,公司通常也会在整个公司范围内采用自己的样式约定。

行长

按照惯例,在C语言中,一行代码的最大长度为80个字符,历史上在较旧的计算机终端安装的标准尺寸显示器上,可以垂直显示24行,水平显示80个字符。尽管现代技术已不再需要将行数限制为80个字符,但仍应将其视为“软停止(soft stop)”的准则,100个字符应该是您用C语言编写的最长的行,否则读者通常会需要进行滚动。如果您需要100个以上的字符,那么可能是时候重新考虑变量名或总体设计了!

// These next lines of code first prompt the user to give two integer values and then multiplies those two integer values together so they can be used later in the program
int first_collected_integer_value_from_user = get_int("Integer please: ");
int second_collected_integer_value_from_user = get_int("Another integer please: ");
int product_of_the_two_integer_values_from_user = first_collected_integer_value_from_user * second_collected_integer_value_from_user;

在其他语言(尤其是JavaScript)中,将行长约束到最大长度以内要困难得多。在那些语言里,您的目标应该是在最大程度地提高可读性和清晰度(例如通过\ n拆分行)。

注释

注释不仅使其他人(例如,您的小组成员)也使您自己更易读懂代码,尤其是在编写和阅读已经经过了数小时,数天,数周,数月的代码的时候。注释太少是不好的,注释太多同样也是不好的。怎样做最好呢?每隔几行代码注释(对那些有趣的代码块)是一个不错的准则。注释应该说清楚下面中的一个或者两个问题:

  1. 这一块代码做了些什么
  2. 我为什么以这种方式实现这一块代码

在函数中,使用“内联注释”并使其简短(例如,只有一行),否则即使使用语法高亮显示,也很难将注释与代码区分开。将注释放在要应用的行上方。无需用完整的句子写出来,但一定要大写注释的第一个单词(除非它是函数,变量等的名称),并在//和注释的第一个字符之间留一个空格,如下所示:

// Convert Fahrenheit to Celsius
float c = 5.0 / 9.0 * (f - 32.0);

换句话说,别这样写:

//Convert Fahrenheit to Celsius
float c = 5.0 / 9.0 * (f - 32.0);

也别这样写:

// convert Fahrenheit to Celsius
float c = 5.0 / 9.0 * (f - 32.0);

在.c和.h文件的顶部应有一个注释,概述程序(或该特定文件)的功能,例如:

// Says hello to the world

同时,在每个函数(也许main除外)的顶部,应该有一个注释,概述函数的功能,例如:

// Returns the square of n
int square(int n)
{
    return n * n;
}

条件语句

条件语句的样式应该如下:

if (x > 0)
{
    printf("x is positive\n");
}
else if (x < 0)
{
    printf("x is negative\n");
}
else
{
    printf("x is zero\n");
}

注意它是如何做的:

  • 花括号很好地排列在一起,每个花括号单独成一行,使分支内的内容清晰明了;
  • 每个if后都有一个空格;
  • 每次对printf的调用都缩进4个空格;
  • ><之间有一个空格;
  • 紧接在每个(之后或紧接在每个)之前没有任何空格。

为了节省空间,一些程序员喜欢将第一个大括号与条件本身保持在同一行,但是我们不建议这样做,因为它较难阅读,因此请勿这样做:

if (x < 0) {
    printf("x is negative\n");
} else if (x < 0) {
    printf("x is negative\n");
}

永远都不要像下面这样做:

if (x < 0)
    {
    printf("x is negative\n");
    }
else
    {
    printf("x is negative\n");
    }

Switch语句

这样声明一个switch语句:

switch (n)
{
    case -1:
        printf("n is -1\n");
        break;

    case 1:
        printf("n is 1\n");
        break;

    default:
        printf("n is neither -1 nor 1\n");
        break;
}

注意它是如何做的:

  • 每个花括号都单独成一行;
  • switch关键字后有一个空格;
  • 紧接在每个(之后或紧接在每个)之前没有空格;
  • switch语句中的每个case都缩进四个空格;
  • 每个case内部都要再缩进四个空格;
  • 每个case(包括default情况)都以break结尾。

函数

按照C99,请务必这样声明main

int main(void)
{

}

或者,如果您使用我们的CS50库,则可以这样做:

#include <cs50.h>

int main(int argc, string argv[])
{

}

或者这样:

int main(int argc, char *argv[])
{

}

甚至可以这样:

int main(int argc, char **argv)
{

}

但是不要这样写:

int main()
{

}

也不要这样写:

void main()
{

}

更不要这样写:

main()
{

}

至于您自己的函数,请务必类似地定义它们,每个花括号都单独成行,并且返回类型与该函数的名称在同一行,就像我们对main所做的那样。

缩进

一次将代码缩进四个空格,以明确哪些代码块位于其他代码块内部。如果使用键盘的Tab键进行此操作,请确保已将文本编辑器配置为将Tab(\ t)转换为四个空格,否则您的代码可能无法在其他人的计算机上正确打印或显示,因为\ t在不同的编辑器上呈现的方式有所不同。 (如果使用CS50 IDE,最好使用Tab进行缩进,而不是反复敲击键盘的空格键,因为我们已将其预先配置为将\ t转换为四个空格。)
这是一些缩进得不错的代码:

// Print command-line arguments one per line
printf("\n");
for (int i = 0; i < argc; i++)
{
    for (int j = 0, n = strlen(argv[i]); j < n; j++)
    {
        printf("%c\n", argv[i][j]);
    }
    printf("\n");
}

循环语句

for

每当需要临时变量进行迭代时,请依次使用ijk,除非更具体的名称将使您的代码更具可读性:

for (int i = 0; i < LIMIT; i++)
{
    for (int j = 0; j < LIMIT; j++)
    {
        for (int k = 0; k < LIMIT; k++)
        {
            // Do something
        }
    }
}

如果您需要三个以上的变量来进行迭代,那么可能是时候重新考虑您的设计了!

while

像这样声明while循环语句:

while (condition)
{
    // Do something
}

注意它是如何做的:

  • 每个花括号都单独成一行;
  • while之后有一个空格;
  • 紧跟在 ( 之后和 ) 之前没有任何空格;
  • 循环的主体(在上述代码中为注释)缩进了4个空格。

do … while

像这样声明do...while循环语句:

do
{
    // Do something
}
while (condition);

注意它是如何做的:

  • 每个花括号都单独成一行;
  • while之后有一个空格;
  • 紧跟在(之后 和)之前没有任何空格;
  • 循环的主体(在上述代码中为注释)缩进了4个空格。

指针

声明指针时,在变量旁边写*,如下所示:

int *p;

请勿将其写在类型旁边,例如:

int* p;

变量

因为CS50使用C99,所以不要在函数的一开始定义所有变量,而要在实际需要的时间和位置之前定义它们。此外,请尽可能严格地限制变量的作用范围。例如,如果仅出于循环目的需要i,请在循环本身内声明i

for (int i = 0; i < LIMIT; i++)
{
    printf("%i\n", i);
}

尽管可以使用ijk之类的变量进行迭代,但是您应该对大多数变量进行更具体的命名。例如,如果您要对一些值求和,请定义变量sum。如果您的变量名称需要两个单词(例如is_ready),请在它们之间加上下划线,这是C语言中的通用约定,但在其他语言中则较少。 如果一次声明多个相同类型的变量,可以一起声明它们,如下所示:

int quarters, dimes, nickels, pennies;

不要初始化一些变量而不初始化另一些变量,像下面这样:

int quarters, dimes = 0, nickels = 0 , pennies;

还应注意将指针与非指针分开声明,如下所示:

int *p;
int n;

不要将指针与非指针变量声明在同一行上,如下所示:

int *p, n;

struct结构体

如下声明一个struct作为类型,每个花括号都单独成一行,并且成员在其中缩进,该struct的名称也单独成一行:

typedef struct
{
    string name;
    string dorm;
}
student;

如果该struct包含一个指向此struct的指针作为成员,请将该struct声明为与该类型相同的名称,而无需使用下划线:

typedef struct node
{
    int n;
    struct node *next;
}
node;
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐