C 语言基础
C 语言是一种通用的、面向过程式的计算机程序设计语言。1972 年,为了移植与开发 UNIX 操作系统,丹尼斯·里奇在贝尔电话实验室设计开发了 C 语言。
C 语言基础
###程序结构
C 程序结构如下:
1 | // 引入头文件。 |
通过指令的编译与执行:
打开一个文本编辑器,添加代码,保存文件为 xxx.c。( C 程序的源文件通常使用扩展名 .c )
打开命令提示符,进入到保存文件所在的目录。
MAC 下的编译使用 clang,Linux 下的编译使用 gcc。
第一种方式:
gcc hello.c,输入回车,编译代码。
如果不指定目标文件名时默认生成的可执行文件名为 a.out 或 a.exe。
键入./a.out
来执行程序。
1 | jianghouren@jianghourendeMacBook-Pro test % clang hello.c |
第二种方式:
gcc/clang -g -o Hello xxx.c
- -g 是 debug 模式,带有调试信息的。
- -o 指明输出文件的名字。
- xxx.c 源代码。
在 Mac 或 Linux 下使用 ./Hello
来执行
1 | jianghouren@jianghourendeMacBook-Pro test % clang -o Hello hello.c |
集成环境的运行,后台其实也是这个步骤。
标识符与关键字
标识符:在编程语言中,就是程序员自己规定的具有特定含义的词,比如类名称,属性名称,变量名等。
关键字:C 中的保留字不能作为常量名、变量名或其他标识符名称。
常用基本类型
在 C 语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式。C 中的类型可分为以下几种:
1、基本类型。它们是算术类型,包括两种类型:整数类型和浮点类型。
short(短整型)、int(整型)、long(长整型)
float(单精度浮点型,一般情况使用 float。)、double(双精度浮点型,精度高,适用于科学计算等。)
char(字符,整数类型。)
2、枚举类型。它们也是算术类型,被用来定义在程序中只能赋予其一定的离散整数值的变量。
3、void 类型。类型说明符 void 表明没有可用的值。(对类型不关心时)
4、派生类型。它们包括:指针类型、数组类型、结构类型、共用体类型和函数类型。
可使用 sizeof 运算符。通过表达式 sizeof(type) 得到对象或类型的存储字节在特定平台上的准确大小。
资料:数据类型
基本运算
- +、-
- *、/、%
1 | int main(int argc,char* argv[]){ |
变量与常量
int a = 0; // 变量,可以再赋值。可以不赋值初始值。
变量在计算机中的物理意义,就是一个寄存器。寄存器是临时存储数据的,它的速度非常快。从内存中取一块数据时,首先存储到寄存器,当改变这个值时,刷新的是寄存器,可擦除。这样可以加快程序的执行速度。
const int LEN = 265; // 常量,不可改变。需要赋值初始值。
在编译程序时,程序中设定了一段静态缓冲区,静态缓冲区是受保护的,通过正常途径是不可修改的。但如果知道内存的具体物理地址,也是可以改变的。
数组
数组是有序的元素序列(C 语言的数组存放的是同一种类型的元素,索引从 0 开始),C 语言中定义数组需要告诉编译器数组的长度。C 语言中数组的定义; char c[2], int arr[10]
1 | int main(int argc,char* argv[]){ |
结构体
1 | // 它是没有保护的概念的(如 private 等) |
1 | // 结构体可以理解为它是一个类 |
枚举类型
枚举可以认为它是一个有限制的整型。一般情况下的使用,是在有一定数值范围的,比如某个属性的取值只能为 1、2、3。
1 | enum em { |
1 | enum em { |
指针
指针就是存放内存地址的变量。地址空间内的存的值,在 C 语言中,它除了可以存放普通的数值,还可以存放另一个内存的地址,这个值就是指针,通过这个值就可以访问到其它地址,然后就可以取出这个地址所存放的数据。所以,这个值可以有多重含义,具体跟业务逻辑相关。
指针的作用:
提升执行效率。
一般情况下,将字符串传入函数中,函数对字符串进行操作时,它是一个拷贝的过程,函数将字符串拷贝到自己的函数空间存放起来。多次的拷贝会对整个 CPU 造成巨大的浪费。而指针,只需要向函数传递这个字符串所在的地址,函数通过指针访问字符串。
更强的控制力。
因为它具有访问地址的能力。像计算机的硬件实际到操作系统层都会有一个对应的映射地址,通过这个地址,C 语言就能访问到硬件设备,并进行控制。C 语言是更底层的语言,它可以访问设备。
指针的操作:
一是对指针本身的操作。
实际就是对地址的操作。比如,当获取某个空间的指针后,可以对这个指针进行加减乘除的操作,对其加一,就指向了下一个空间。
二是对所指向的内容操作。
指针指向某一个内存地址时,可以获取其内容,可以对这个内容进行加减乘除的操作。
指针的定义与使用:
type* var:
- type 指类型,比如 int、void 等。
- 而 * 代表这个变量是一个指针,可以靠近类型 type 写,表示这种类型的指针,关注指针是什么类型的,也可以靠近变量 var 写,表示这个变量是一个指针,而对类型不关注。这两种写法对编译器是没有区别的,但在编写代码时,最好统一风格。
*var:表示获取指针所指向的内容
堆内存的分配与释放:
分配内存:void* mem = malloc(size);
释放内存:free(mem);
1 |
|
常见的内存空间
栈空间:栈的机制,后进先出。最大的特点是,在 C 语言中写的函数,在函数内所分配的所有变量都是在栈空间分配的,当从函数退出时,从栈空间分配的资源会被自动释放。(分配的资源是有限的,默认每个函数栈空间的大小是 8兆。)
堆空间:需要明确的使用 malloc() 函数来分配资源,使用完内存后,要通过 free() 函数将资源释放回堆空间,这样别人使用时还能从堆空间分配资源。(分配的资源几乎可以认为是无限的,适合需要大空间的时候。)
内存映射:像一些动态库一般都是将它直接导入内存映射区,也是一段专门的空间。比如将某个文件直接映射到内存中,文件的内容与内存形成映射关系,当改变内存中的值时,会直接在系统内部自动更新到文件中。
Linux 内存地址的划分:4G 32 位系统
0 ~ 0x08048000:这段是受保护空间,我们的进程是不能访问的。
code:存放的是进程所要执行的代码段。
堆空间的增长是从下向上,栈空间是从上向下,每次分配空间是向下走的。堆空间与栈空间这样的划分是为了减少冲突。
共享库,或者叫内存映射区,当想通过内存改变文件时,就可以将文件映射到 mmap 这段空间中。
内存泄漏:
- 不断的向系统申请内存。
- 申请的内存不用,也不释放。
野指针:占用别人的内存称为野指针。
条件判断与循环
比较运算:>、<、>=、<=、==、!=
if/else 语句:
if( a> b){
…
}else{
…
}
for 语句:
for(int i =0; i<100; i++){
…
}
while 语句:
1 |
|
函数
C 语言中的命名一般以 Linux 的风格,单词与单词用下划线连接,单词一般都是缩写。
1 | // void 返回类型 |
函数指针:指向函数的指针变量。通过 C 语言的函数指针可以实现 C++ 中的多态,就是定义的函数指针既可以指向 a 函数,也可以指向 b 函数,对外层来说,只需要调用这个函数指针就可以了。(多态就是指一个函数可以有不同的含义)
函数指针的格式:返回值类型 (*指针变量名) ([形参列表]);
1 | int func(int x); // 声明一个函数 |
1 |
|
文件操作
文件类型:FILE* file; (FILE* 在 Linux 下叫指针,在 Windows 下叫句柄。)
打开文件:FILE* fopen(path,mode);
关闭文件:fclose(FILE*);
1 |
|
备注
参考资料:
慕课网-音视频基础(李超)
欢迎关注微信公众号:非也缘也