重走C语言之路(二)

1,032 阅读6分钟

重走C语言之路(二)

1. 简单程序结构

已经看过一个C语言的Hello World程序了,那么如果要写一个C语言的简单程序,需要满足什么样的基本结构呢?

在C语言当中,程序是由一个或多个函数组成的,并且其中必须包含有main()

函数头和函数体组成函数,而函数头的内容又包括函数名、入参、返回类型

image.png

函数体便是{}包裹起的代码块,主要是声明、语句的组合

因此,明白了这些,大概可以构思一下一个基本程序的结构,大概是这样:

// 预处理、声明等

int main() 
{
    // 若干声明、语句、函数
    return 0;
}

程序有一个main()用作入口,其他部分基本都是需要添加的,根据需求补充函数、声明、语句等,组织成有意义的逻辑,必要的时候可能还需要额外添加预处理语句等,在此基础上其他的都是填空,可以由少到多地进行一步步地尝试

2. 程序的可读性

为什么还没怎么开始写,就开始叨叨可读性呢?因为习惯性的东西还是尽早提出来比较好,之后可以不断地在实践中加深

刚开始的时候,我们可能往往只是注重于实现功能本身,但是随着自己越来越熟悉语言,项目代码随之膨胀起来之后,我们会逐渐发现,可读性高的代码真的是太重要了,无论是排查问题、性能优化、重构等都能有条理地展开;而难度的代码会浪费掉你很多时间,而且容易在不注意的地方留下定时炸弹

变量、函数的命名尽可能遵循易读的法则,比如count就比c好,至少能够大概猜一猜这个变量可能是用于计数的

另外,如果实在不方便使用变量、函数名等说清,可以使用注释进行辅助说明,在关键逻辑的语句之前使用注释补充说明,或者标记参考

并且巧妙利用空行和换行也是可读性里重要的一环,相关的语句可以扎堆儿写,利用空行将代码逻辑分成一块块

#include <stdio.h>

int main() 
{
    // 声明-1部分
    int a, b, c;

    // 赋值-2部分
    a = 1;
    b = 2;
    c = 3;

    // 输出-3部分
    printf("");

    return 0;
}

像上面这样,几个部分就感觉很清晰,分工明确,很有条理

语句本身就是以;结束,没有必要拖拖拉拉写在一行,每行不宜过长,就像上面那样,简洁明了,如果实在比较长可以考虑以整洁的格式多行呈现,必要时配上相应的注释

printf(
        "先输入参数一%d, 再输入参数二%d, 二者求和=%d",
        a,
        b,
        a + b);

3. 程序调试

在真正编写程序的时候,我们往往需要通过调试来检测程序当中可能存在的问题

在项目的规模逐渐膨胀时,逻辑也会更加复杂,许多问题不能够一目了然,可能需要等发现了再去排查修复,掌握一定的调试技巧可以大大提高效率

常见的问题主要分为语法错误语义错误

语法错误通常能够由编译器帮忙检查出来,因为编写的代码需要满足C语言的语法规范,而语法规范是一个确定的规范,因此当程序编写不规范时,编译器通常可以及时发现,并且标识出问题的位置

image.png

比如像这里,缺少分号的问题可以及时被发现

语义错误往往难以排查,至少编译器帮不了你,因为编译器不会知道你写一段程序想要表达什么,它只会机械地检测是否违反既有的语法,因此,语法问题通常更加难以排查

你可以通过自己阅读程序,梳理逻辑,或者使用断点调试功能进行程序的单步执行

具体的内容将会在后面专门展开~~

4. 关键字和保留字

关键字是C语言的词汇,这些词是不能随便拿来用作标识符的,像int表示的是整数类型,for表示的是循环,都有各自专门的用途

关键字说明
auto声明自动变量
break跳出当前循环
case开关语句分支
char声明字符型变量或函数返回值类型
const定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变
continue结束当前循环,开始下一轮循环
default开关语句中的"其它"分支
do循环语句的循环体
double声明双精度浮点型变量或函数返回值类型
else条件语句否定分支(与 if 连用)
enum声明枚举类型
extern声明变量或函数是在其它文件或本文件的其他位置定义
float声明浮点型变量或函数返回值类型
for一种循环语句
goto无条件跳转语句
if条件语句
int声明整型变量或函数
long声明长整型变量或函数返回值类型
register声明寄存器变量
return子程序返回语句(可以带参数,也可不带参数)
short声明短整型变量或函数
signed声明有符号类型变量或函数
sizeof计算数据类型或变量长度(即所占字节数)
static声明静态变量
struct声明结构体类型
switch用于开关语句
typedef用以给数据类型取别名
unsigned声明无符号类型变量或函数
union声明共用体类型
void声明函数无返回值或无参数,声明无类型指针
volatile说明变量在程序执行中可被隐含地改变
while循环语句的循环条件

后续在C99标准中又追加了5个关键字

_Bool_Complex_Imaginaryinlinerestrict

C11新增7个关键字

_Alignas_Alignof_Atomic_Generic_Noreturn
_Static_assert_Thread_local

其实经常写写,熟悉了自然能够分辨,没有必要刻意进行记忆

除了关键字不能用于标识符,还有保留字,主要是一些标准库中的函数的名称,也是有特定的用途,尽量避免使用,从而引起一些问题

5. 标识符

既然都已经说到关键字和保留字了,那么就有必要谈谈重要的标识符概念了

标识符其实就是C语言当中用来标识变量、函数、以及一些其他用户自定义项目的名称,主要是给开发者起名字制定的规范

具体的规则就是标识符要以大写或者小写字母、数字、下划线组成,并且不能以数字开头(也要避开关键字和保留字,就像古代起名不能犯皇帝名讳一样)

像mPlan02、_count、a23、last_name这些都是合法的标识符

并且C语言严格区分大小写,map和MAP代表就是完全不同的东西

标识符在编写程序的过程中被大量的使用,如果想要确保程序清晰整洁,在确保标识符合法的情况下,具体的名字如何组织也得好好斟酌