Skip to main content

C语言常见概念

C语言

人和人交流使用自然语言(如汉语、英语、日语),人和计算机交流则需要计算机语言。现有的计算机语言有上千种,程序员通过这些语言编写程序来向计算机下达指令。

C语言是其中的一种,并且历经多年仍然在计算机语言排行榜上名列前茅。除 C 语言外,像 C++、Java、Go、Python 等也是常见的计算机语言。

C语言历史

C 语言的诞生与 UNIX 操作系统密切相关。其发展历程大致如下:

1969发明 B 语言 KenThompson & DennisRitchie 基于 BCPL 为Unix 编写1972发明 C 语言 DennisRitchie & BrianKernighan重新设计,取代 B1973Unix 系统用 C 重写 促成C 的快速流行1988C 语言标准化 ANSI发布首个官方标准至今C 依旧活跃常年位列编程语言前三C 语言发展历程

1969 年 Ken Thompson 在 BCPL 的基础上发明了 B 语言 用于移植 UNIX 内核。

1972 年 Dennis Ritchie 与 Brian Kernighan 在 B 语言的基础上重新设计出一种更高级的语言,命名为 C 语言。

1973 年整个 UNIX 系统都使用 C 重写,这种语言迅速流传并成为编写操作系统和系统软件的主力。

1988 年 ANSI 发布 C 语言标准化。

直到今天,C 语言仍然广泛使用。

编译器

编译和链接

C语言是一门编译型计算机语言,C语言源代码都是文本文件,文本文件本身无法执行,必须通过编译器翻译和链接器的链接,生成二进制的可执行文件,可执行文件才能执行。

C语言代码是放在 .c 为后缀的文件中,要得到最终运行的可执行程序,中间要经过编译和链接 2 个过程。

C语言把 .c 为后缀的文件称为源文件,把 .h 为后缀的文件称为头文件。

一个工程一般都会有多个源文件组成,如下演示了源程序经过编译器和链接器处理的过程:

链接

编译

test.c

编译器
cl.exe

add.c

xxx.c

test.obj

add.obj

xxx.obj

链接库

链接器
link.exe

可执行程序
xxx.exe

每个源文件(.c)单独经过编译器处理生成对应的目标文件(.obj 为后缀的文件)。

多个目标文件和库文件经过链接器处理生成对应的可执行程序(.exe 文件)。

编译器对比

C语言是一门编译型的计算机语言,需要依赖编译器将计算机语言转换成机器能够执行的机器指令。

  • VS2022 集成了MSVC,安装报包较大一些,安装简单,无需多余配置,使用起来非常方便。
  • XCode 集成了clang,苹果电脑上的开发工具。
  • DevC++ 集成了gcc,小巧,但是工具过于简单,对于代码风格的养成不好,一些竞赛使用。
  • Clion 是默认使用 CMake,编译器是可以配置的,但工具是收费。

集成开发环境(IDE)用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。

示例程序

如下为一个简单的 C 程序,它在屏幕上输出一行文本:

#include <stdio.h>

int main()
{
printf("hello C\n");
return 0;
}

运行时,程序会从 main 函数开始执行,调用标准库函数 printf 打印字符串 hello C,最后通过 return 0 返回。

main函数

每个 C 程序必须有且只有一个 main 函数。无论源代码中包含多少其他函数,程序都是从 main 开始执行的,因此它被称为程序的入口,也被叫做主函数。

  • main 函数前面的 int 表示它会返回一个整型值,通常在函数尾部通过 return 0; 表示程序正常结束。
  • 项目中只能存在一个 main,否则链接阶段会报多个入口点的错误。

库函数

printf

printf 属于 C 标准库中的输入/输出函数,用于将信息打印到标准输出设备,使用时需要包含 stdio.h 头文件。

#include <stdio.h>

printf 使用占位符来控制格式,例如 %d 表示打印整型、%c 表示打印字符、%lf 表示打印 double 类型。打印字符串可以使用 %s 或直接将字符串常量放在参数中。

printf("hello C\n");

库函数

为了不再重复实现常见的代码,让程序员提升开发效率,C语言标准规定了一组函数同的编译器厂商根据标准进行实现,库,这些函数也被称为库函数。在这个基础上一些编译器厂商可能会额外扩展提供部分函数(这些函数其他编译器不一定支持)。

一个系列的库函数一般会声明在同一个头文件中,所以库函数的使用,要包含对应的头文件。C库函数

关键字

C 语言保留了一批具有特殊含义的符号,它们称为关键字或保留字。

  • 关键字都有特殊的意义,是保留给C语言使用的。
  • 程序员不能把关键字用于自定义标识符名称。
  • 关键字不能自己创建。

C89 标准规定了 32 个关键字,包含:

关键字关键字关键字关键字
auto break case char
const continue default do
double else enum extern
float for goto if
int long register return
short signed sizeof static
struct switch typedef union
unsigned void volatile while

C99 引入了 inlinerestrict_Bool_Complex_Imaginary 等关键字,但使用最多的仍是上表中的 32 个,更多可参考C语言关键字

ASCII编码

键盘能够输入各种符号,例如 aq@# 等,这些单个符号称为字符。在 C 语言中,字符用单引号包围,例如 'a''b''@'

计算机内部所有数据都以二进制形式存储,为了统一字符的二进制表示,美国国家标准学会(ANSI)制订了 ASCII 编码,C 语言采用 ASCII 表对字符编码。

decocthexchdecocthexchdecocthexchdecocthexch
00000NUL(空) 3204020(空格) 6410040@ 9614060`
10101SOH(标题开始) 3304121! 6510141A 9714161a
20202STX(正文开始) 3404222" 6610242B 9814262b
30303ETX(正文结束) 3504323# 6710343C 9914363c
40404EOT(传送结束) 3604424$ 6810444D 10014464d
50505ENQ(询问) 3704525% 6910545E 10114565e
60606ACK(确认) 3804626& 7010646F 10214666f
70707BEL(响铃) 3904727' 7110747G 10314767g
80808BS(退格) 4005028( 7211048H 10415068h
90909HT(横向制表) 4105129) 7311149I 10515169i
100a0ALF(换行) 420522a* 741124aJ 1061526aj
110b0BVT(纵向制表) 430532b+ 751134bK 1071536bk
120c0CFF(换页) 440542c, 761144cL 1081546cl
130d0DCR(回车) 450552d- 771154dM 1091556dm
140e0ESO(移入) 460562e. 781164eN 1101566en
150f0FSI(移出) 470572f/ 791174fO 1111576fo
161010DLE(退出数据链) 48060300 8012050P 11216070p
171111DC1(设备控制1) 49061311 8112151Q 11316171q
181212DC2(设备控制2) 50062322 8212252R 11416272r
191313DC3(设备控制3) 51063333 8312353S 11516373s
201414DC4(设备控制4) 52064344 8412454T 11616474t
211515NAK(反确认) 53065355 8512555U 11716575u
221616SYN(同步空闲) 54066366 8612656V 11816676v
231717ETB(传输块结束) 55067377 8712757W 11916777w
241818CAN(取消) 56070388 8813058X 12017078x
251919EM(媒介结束) 57071399 8913159Y 12117179y
261a1ASUB(替换) 580723a: 901325aZ 1221727az
271b1BESC(退出) 590733b; 911335b[ 1231737b{
281c1CFS(文件分隔符) 600743c< 921345c\ 1241747c|
291d1DGS(组分隔符) 610753d= 931355d] 1251757d}
301e1ERS(记录分隔符) 620763e> 941365e^ 1261767e~
311f1FUS(单元分隔符) 630773f? 951375f_ 1271777fDEL(删除)

详细可参考ASCII码

左侧 0〜31 的代码表示控制字符,不可打印。

十进制 32 对应空格,后续依次是可打印的标点、数字、大写字母、小写字母以及若干符号。

大写字母 A〜Z 的 ASCII 码为 65〜90

小写字母 a〜z97〜122

数字字符 0〜948〜57,对应的大写和小写字母相差 32

换行 \n 的 ASCII 值是 10

#include <stdio.h>

int main()
{
int i = 0;
for (i = 32; i <= 127; i++)
{
printf("%c ", i);
if (i % 16 == 15)
{
printf("\n");
}
}
return 0;
}

字符串

C语言中的字符川使用双引号括起来的一串字符就被称为字符串,如:"abcdef",就是一个字符串。

字符串的打印格式可以使用 %s 来指定,也可以直接打印如下:

#include <stdio.h>

int main() {
printf("%s\n", "hello C");
printf("hello c");
return 0;
}

C语言字符串中一个特殊的地方,在字符串的末尾隐藏放着一个 \0 字符,这个 \0 字符是字符串的结束标志。

使用库函数 printf() 打印字符串或者 strlen() 计算字符串长度的时候,遇到 \0 的时候就动停止了。

C语言中也可以把一个字符串放在一个字符数组中:

#include <stdio.h>

int main() {
char arr1[] = {'a', 'b', 'c'};
char arr2[] = "abc";
printf("%s\n", arr1);
printf("%s\n", arr2);
}

运行后可以看到,arr1 字符数组在打印的时候,打印 a b c 之后打印了一些随机值,这是因为为 arr1 在末尾的地方没有 \0 字符作为结束标志,不知道何时停止。

arr2 的打印就是完全正常的,就是因为 arr2 数组是使用字符串常量初始化的,数组中有 \0 作为结束标志,打印可以正常停止。

如果在 arr1 数组中单独放一个 \0,那么都是打印到 \0 的时候就停止了。

转义字符

字符中有一组特殊的字符是转义字符,转义字符顾名思义:转变原来的意思的字符。

C语言中常见的转义字符有:

转义序列说明
\?在书写连续多个问号时使用,防止它们被解析成“三字母词”(在现代编译器上已难以重现)。
\'表示字符常量 '
"在字符串内部表示双引号
\表示反斜杠本身,避免被解析成转义序列起始符
\a警报;终端响铃或闪烁,或两者同时发生
\b退格;光标回退 1 个字符,但不删除字符
\f换页;光标移到下一页(现代系统多表现为垂直制表,类似 \v
\n换行
\r回车;光标回到当前行行首
\t水平制表;光标跳到下一个制表位,通常为 4/8 的倍数位置
\v垂直制表;光标移到下一行同一列的位置
\ddd1–3 位八进制数字表示字符,例如 \130 表示字符 X
\xdd2 位十六进制数字表示字符,例如 \x30 表示字符 0
\0NULL 字符;作为字符串结束标志,其 ASCII 码为 0(属于 \ddd 形式的特例)

详细可参考 转义字符

语句

C语言的代码是由一条一条的语句构成的,C语言中的语句可为以下五类:

  • 空语句。
  • 表达式语句。
  • 函数调用语句。
  • 复合语句。
  • 控制语句。

空语句

空语句是最简单的,一个分号就是一条语句,是空语句。

#include <stdio.h>

int main() {
;//空 语 句
return 0;
}

空语句一般出现的地方是:这里需要一条语句,但是这个语句不需要做任何事,就可以写一个空语。

表达式语句

表达式语句语句就是在表达式的后边加上分号。如下所示:

#include <stdio.h>

int main() {
int a = 20;
int b = 0;
b = a + 5; //表达式语句
return 0;
}

函数调用语句

函数调用的时候,也会加上分号,就是函数调用语句。

#include <stdio.h>
int Add(int x, int y) {
return x+y;
}

int main() {
printf("hehe\n"); //函数调用语句
int ret = Add(2, 3); //函数调用语句
return 0;
}

复合语句

复合语句其实就是代码块,成对括号中的代码就构成一个代码块,也被称为复合语句。

int main() {
int i = 0;
int arr[10] = {0};

for(i=0; i<10; i++) {
arr[i] = 10-i;
printf("%d\n", arr[i]);
}

return 0;
}

控制语句

控制语句用于控制程序的执行流程,以实现程序的各种结构方式择结构、循环结构),它们由特定的语句定义符组成,C语言有九种控制语句。

  • 条件判断语句也叫分支语句:if 语句、switch 语句。
  • 循环执行语句:do while 语句、while 语句、for 语句。
  • 转向语句:break 语句、goto 语句、continue 语句、return 语句。

注释

注释是对代码的说明,编译器会忽略注释,也就是说,注释对实际代码没有影响。

注释是给程序员自己,或者其他程序员看的。好的注释可以帮我们更好的理解代码,但是也不要过度注释,不要写没必要的注释。

编译时,注释会被替换成一个空格。

/* 注 释 */

/*
这是一行注 释
*/

// printf("a ");
/*
printf("b ");
printf("c ");
*/
printf("d ");