C chapter1 基本概念
前言
本文程序开发基于 Ubuntu 环境下的 gcc 编译器。
本着没整理就是没学习的原则,菜鸡的我又来学 C 了。
前面学 C 都是学到在 CTF 中够用就行了,不过这次打算一定要把 C 研究透。
基本结构
C 中一个程序最基本的结构就是头文件和主函数,以下列代码为例。
头文件就是使用#include
包含的库文件,即stdio.h
这样。
以下库文件就是最常用的库stdio.h
库,因为它是输入输出标准库,我们要调用其中函数输入输出内容。
主函数就是main
函数,是程序的入口函数,笼统的说程序从这里开始执行。
我们需要将以下代码保存为后缀名为.c
的源文件,然后使用 gcc 编译器进行编译。
经典程序 Hello,world!
利用stdio.h
标准输入输出库中的printf
函数输出文本。
输出的文本中\n
是一个转义字符表示换行。
下面这行程序输出一行指定文本
1 |
|
printf函数
用于格式化输出到标准输出(屏幕)。
其基本语法如下:
1 |
|
函数括号中的是函数参数。
printf
参数format
:格式化字符串,用于指定输出的格式。格式化符号如%d
、%f
、%s
等用于显示不同类型的数据。%d
:表示输出整数%f
:表示输出浮点数%c
:表示输出字符%s
:表示输出字符串
...
可变参数,根据format
字符串中指定的格式进行匹配。
字符
字符规则就像英语中的拼写规则,决定你在源程序中如何形成单独的字符片段,也就是标记(token)。
一个 ANSI C 程序由声明和函数组成。函数定义了需要执行的工作,而声明则描述了函数和(或)函数将要操作的数据类型(有时候是数据本身)。
标准规定 C 字符集必须包括英语所有的大写和小写字母,数字 0 到 9,以及下面这些符号:
! | “ | # | % | ‘ | () | + | , | - | . | / | ? |
; | <> | = | ? | [] | \ | ^ | _ | {} | | | ~ |
三字母词
三字母词(trigrph),三字母词就是几个字符的序列,合起来表示另一个字符。三字母词使 C 环境可以在某些缺失一些必需的字符的字符集上实现。
常见三字母词:
??( [ | ??< { | ??= # |
??) ] | ??> } | ??/ \ |
??! | | ??’ ^ | ??- ~ |
两个问号开头再尾随一共字符一般不会出现在其它表达式中,所以把三字母词用这种形式来表示,这样就不致于引起误解。 |
当你编写某些 C 代码时,你在一些上下文环境里想使用某个特定的字符,却可能无法如愿,因为该字符在这个环境里有特别的意义。例如,双引号 “ 用于界定字符串常量,你如何在一个字符串常量内部包含一共双引号呢?这个适合就需要通过转义字符了。
转义字符
C 语言的转义字符用于表示那些不能直接在字符串中输入的字符。
常见的转义字符包括:
符号 | 含义 |
---|---|
\‘ | 单引号 |
\“ | 双引号 |
\? | 问号 |
\\ | 反斜线 |
\a | 响铃 |
\b | 退格 |
\f | 分页符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
标识符
标识符(indentifier)就是变量、函数、类型等的名字。它们由大小写字母、数字和下划线组成,但不能以数字开头。
C 是一种大小写敏感的语言,所以 abc、Abc、abC 和 ABC 是 4 个不同的标识符。
标识符的长度没有限制,但标准允许编译器忽略第 31 个字符以后的字符。标准同时允许编译器对用于表示外部名字(也就是由链接器操纵的名字)的标识符进行限制,只识别前六位不区分大小写的字符。
下列 C 语言关键字是被保留的,它们不能作为标识符使用:
auto | do | goto | signed | unsigned |
break | double | if | sizeof | void |
case | else | int | static | volatile |
char | enum | long | struct | while |
const | extern | register | switch | continue |
float | return | typedef | default | for |
short | union |
注释
注释用于在代码中添加说明文字,帮助他人理解代码的功能和意图。
注释不会被编译器执行,因此不会影响程序的运行。
C 语言支持两种类型的注释:
单行注释
1 |
|
多行注释
1 |
|
注意:注释不能够嵌套使用
定义变量
这里我们只介绍基本整型变量,详细的后面会讲述。
常见的变量类型有:
char
:一般用于表示单个字符short
:占两个字节的整型int
:占四个字节的整型long
:至少2个字节,可能是4个字节。
以下代码声明了一个int
型的变量并初始化值为 10。
利用printf
格式化函数输出变量。
实例
1 |
|
scanf函数
前面的printf
函数用于输出内容,这里的scanf
函数用于输入内容。
既然要输入内容,那么输入的内容就必须要有地方存储。
我们采用上面提到的变量来存储它。
1 |
|
- 参数
format
:格式化字符串,用于指定输入的数据类型。- 常用格式化符号
%d
:整数%f
:浮点数%c
:字符%s
:字符串
...
可变参数,用于存储输入的数据。每个变量应对应格式化字符串中的格式符。scanf
参数变量前必须加&
。
示例
下面代码定义了一个int
变量 a 用于接收输入内容。
然后利用printf函数将输入的内容打印出来。
1 |
|
计算两数之和
以下程序定义了 3 个变量。
先利用printf
函数输出提示信息。
通过scanf
函数输入两个数,然后计算两个数的和存储到第三个变量。
之后利用printf
格式化输出将和输出。
1 |
|
Makefile
Makefile 是一种自动化构建工具的配置文件,通常用于管理和自动化编译程序的过程。它定义了如何从源代码生成目标文件,以及在目标文件发送变化时如何重新构建这些文件。以下是 Makefile 的基本概念:
- 目标(Target):需要生成的文件,如可执行文件或中间文件。目标通常是文件名,如
hello
。 - 依赖(Dependency):目标文件生成所依赖的源文件或其它目标文件。例如,
hello
依赖于main.o
和printhello.o
。 - 规则(Rule):指定如何从依赖文件生成目标文件的命令。规则通常包括目标文件、依赖文件以及执行的命令。
- 变量(Variable):用于定义可重复使用的值,如编译器或编译选项。变量简化了 Makefile 的编写和维护。例如,
C=gcc
。 - 伪目标(Phony Target):不代表实际文件的目标,如
clean
,用于执行特定的操作,如删除生成的文件。
在 Linux 下进行 C 语言程序开发我们离不开 Makefile,Makefile 可以提升我们管理代码和编译代码的效率,可以避免重复工作。
我们利用 Makefile 来编译上述程序
使用 Makefile 的前提是系统上要安装 make 工具。
Ubuntu下可以执行如下命令安装。
1 |
|
1 |
|
将 Makefile 保存到代码文件目录命名为 Makefile。
然后使用make
命令进行编译。
直接在命令行执行 make 命令即可。
对于上述 Mkaefile我们也可以写成下面这样,增加通用性。
1 |
|
上面的 Makefile 可以通过使用 make clean
命令清理掉编译后的可执行文件,便于重新编译。
这些都是比较简单的,随着对 C 的学习我们还会编写更复杂的 Makefile。