语言关键字:

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

常用的Linux系统命令:

touch/cat/more/head/tall/rm/cp/mv
mkdir/rmdir/cd/ls/tar
ifconfig/ping/telnet/ssh/ftp

vim文本编辑器:

在终端下依靠键盘操作使用的文本编辑器。
三大主要模式:正常模式、插入模式、命令模式
常用快捷键:Ctrl+x Ctrl+z Ctrl+c
教程:vimtutor

C语言介绍:

发明C语言的目的是什么
长盛不衰
优缺点、特点
C语言三剑客:《C语言陷阱和缺陷》、《C和指针》、《C专家编程》、《C程序设计语言》、《C Primer Plus》、《必然》、《白说》

编译器介绍:

编译器就一个特殊的程序,把负责把C代码(文本文件)编译成可执行的二进制文件。
它由:预处理器、编译器、链接器组成
常用的参数:-E -c -S -o -std -l -D -Werror -Wall
E	激活预处理;头文件、宏等展开(.i文件)
S	激活预处理、编译;生成汇编代码(.s文件)
c	激活预处理、编译、汇编;生成目标文件(.o文件)
o	生成目标
Wall	打开编译告警(所有)
g	嵌入调试信息,方便gdb调试
《程序员的自我修养》

数据类型:

整型:unsigned、signed
char,short,int,long,long long
实型:float,double,long double
字符:char
布尔:bool
取值范围:char,short,int
各类型的字节数:
各类型的占位符:long double(%LF)

进制转换:

为什么需要二进制:因为现在的计算机由大规模集成电路构成,计算单元只能识别高低电流这种数据,
因此只能使用二进制数据。
为什么需要八进制:为了方便记录二进制,由于历史原因八进制数据还在使用。
为什么需要十六进制:相当于升级版的八进制,由于计算机的高速发展,八进制已经无法满足需要。
十进制转换成二进制:
	求余:把十进制数据不停的用2求余,逆序记录求余的结果。
		189 % 2 = 1
		94 % 2 = 0
		47 % 2 = 1
		23 % 2 = 1
		11 % 2 = 1
		5 % 2 = 1
		2 % 2 = 0
		1 % 2 = 1
		10111101
	求权:128 64 32 16 8 4 2 1
二进制转换成十进制:
	2的不同次方相加。
二进制转换成八进制:三位二进制转换成一位八进制
	10 111 101 = 0275
	128 56 5 = 189
二进制转化成十六进制:四位二进制转换成一位十六进制
	10 <=> a
	1011 1101 = 0xbd
0b10111101 二进制
0275 八进制
0xbd 十六进制

数据在内存是如何存储的:
	数据分为原码、反码、补码,内存中存储的是数据的补码。
原码:数据直接转换成的二进制(无论正负)
反码:将原码按位求反得到反码
补码:
	正:原码
	负:反码+1
补码:10111101 char
    10111100
    01000011 -67

常量与变量

常量:程序运行过程中不可改变的数据
    字面值
	100 int类型
	100L long
	100U unsigned int
	100LU unsigned long
	100LL long long
	100LLU unsigned long long
	3.14 double
	3.14F float
	3.14LF long double
    枚举值
    宏常量
    具有const属性的被初始化过的全局变量
变量:类型 变量名;注意:取名规则,见名知意
    容器、数据

流程控制

if else,switch,for,while,do while,break,continue,goto
注意:大括号不要省略,分号不要多加
《C语言编码规范-华为》
《C++语言编程规范-谷歌》
如何判断XX类型是否是“零值”?
float,bool,int,char,int* p;
if(0.000001 > f && f >-0.000001)
if(flag)
if(0 == num)
if('\0' == ch)
if(NULL = p)
阅读、安全角度思考。

数组

C语言中只有一维数组,多维数组都是使用一维数组模拟的。
数组的越界:一切正常、段错误、脏数据。
char str[11] = "hello,world";
变长数组:数据的长度填写变量,编译时不能确定,程序运行期间可以变化,而执行数组定义语句时长度才固定下来。
	优点:可根据实际情况定义数组的长度,从而节约内存
	缺点:不能初始化。
int arr[10];
arr <=> int *
int arr[3][4]
arr <=> int (*)[4];

函数

函数是C语言中管理代码的最小单位,命名空间独立,栈空间独立。
函数被调用时开辟栈内存,函数结束后释放栈内存。

声明:返回值 函数名(类型1,类型2,...);
定义:返回值 函数名(类型1 参数名1,类型2 参数名2,...)
{
	函数体
}
注意:函数的定义如果出现调用之前,声明可以忽略
注意:调用函数时如果没有找到函数声明,也没有定义,编译器也不报错,而是先猜测函数的格式,链接时在尝试寻找函数的定义。
	return 语句只是把数据存储到一个特定的位置,当函数运行结束后,调用者就可以从这个位置获取到返回值。
		函数有返回值(格式),而没写return语句,调用者会得到一个不确定的返回值。

常见编译错误:
	隐式声明函数,没有找到函数声明和定义。1
	undefined reference to '',有函数声明,但无函数定义
函数的本质:函数就是存储在代码段中的一段数据(二进制指令的集合),函数名就是这段数据的开始位置
	因此函数名就是地址,可以定义指向这段数据的指针变量,
	返回值 (*函数指针) (类型1,类型2,...);

函数的传参:
		1、只能值传递(内存拷贝),使用指针可提高效率(const int *)
		2、函数之间共享变量,全局变量(尽量少用),指针(注意安全)
		3、数组当作函数的参数时就蜕变成了指针(长度丢失),额外增加一个参数传递数组长度。
修饰变量的关键字
auto:用来修饰自动创建、释放的变量(局部变量、块变量),不加就代表加。
	注意:静态变量、全局变量不能用它来修饰。

static:
	限制作用域:全局变量、普通函数
	改变存储位置:把局部变量、块变量的存储位置由栈改为bss、data
	延长生命周期:把局部变量、块变量的生命周期延长与全局变量一样。
	static int fun(void);

const:为数据提供一种"保护"机制,变量被它修饰后就不能显示修改。
	也可以修饰函数的参数、返回值等。
	const int fun(void);

volatile:告诉编译器此变量的值不稳定、易变(不优化变量的取值)。
	多线程共享变量、硬件编程(裸机、驱动)

register:申请把变量的存储位置改为寄存器,但申请不一定成功
	注意:被它修饰过的变量不能取地址

extern:声明变量,用于不同.c之间共享全局变量(只能解决编译时问题)
 
注意:全局变量、局部变量、块变量的变量名可以同名,由于作用域不同,会互相屏蔽。
	块变量 > 局部变量 > 全局变量 (块变量屏蔽同名的局部变量)

程序在内存的分段:

代码段 test:存储的是代码所编译成的二进制指令、字符串字面值、常量
	具有只读属性,一旦修改会发生段错误。
全局数据段 data:初始化过的全局变量、静态变量
bss段(静态数据段):未初始化的全局变量、静态变量
	程序运行前会清理为0;
栈 stack:存储局部变量、块变量、大小有限,安全。
	由操作系统管理,以函数为单位使用(函数调用结束后自动释放)。
堆 heap:一般由程序员手动管理(让系统去映射),与指针配合使用,足够大,使用麻烦,释放的时间受控制
	但不安全,容易产生内存碎片、内存泄漏。