C语言基础
软件生成
预编译、编译、汇编、链接
内存划分
代码段/数据段(初始化的全局变量、静态全局和局部变量)/BSS段(未初始化的全局变量、静态全局和局部变量)/堆(malloc分配的内存)/栈(函数内临时变量、上下文)
[OS布局在低地址][Code][Data][BSS][heap(低往高)][stack(高往低)]
全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对其初始化。
普通局部变量存储于进程栈空间,使用完毕会立即释放
静态局部变量在全局数据区分配内存空间;编译器自动对其初始化
变量生存周期
全局变量,同main函数周期
静态全局变量(限制在定义的文件内部访问)
局部变量,语句块{}}弹栈截止
静态局部变量(同全局变量,但限制在{}}范围内)
函数参数,开辟栈空间开始,退出系统弹栈结束
sizeof是操作符,所以在预编译阶段计算出数值
运算符与表达式
不要使用define替换typedef 定义数据类型别名
例如:#define D_INT32 int *
D_INT32 ptr_a,ptr_b;
展开后 int * ptr_a,ptr_b 而不是 int * ptr_a,*ptr_b
指针变量与指针常量(数组)
char c[5]={1} c为数组首地址,是一个常量不可修改
char * p =c p为指针变量名,可修改
&c+1 ,偏移整个数组,此处偏移5个字节&p+1,偏移4或8字节
下面的函数参数是一个数组么?
void func(int input[100]) 不,他是一个指针,input指向一个int [100]数组
数组地址和数组首地址的区别?
例如:int a[10]; int *p = a; int (*q)[10] = &a
a只是a[0]的数组首地址,a+1就是a[1]的地址了
&a是整个a[10]的数组地址 &a + 1 已经偏移了10个字节
指针与结构体
struct Mystruct {
int a;
int b;
} ss = {1,2};
Mystruct *ptr = &ss;ptr->a; 基于指针访问结构体typedef void *HANDLE ,这是typedef定义,HANDLE相当于void *,们能够叫它披着句柄皮的指针;对于void* ,它作为函数參数or函数返回值,可以接受任意类型的指针;
指针的危险动作(内存破坏)
错误的强制类型转换
char s = 'a';
int *ptr;
ptr=(int *)&s;
*ptr=12; s占一个字节,赋值语句把s相邻的 高地址方向 的三个字节破坏掉了。
错误的指针运算
int *ptr; int a
ptr = &a;
ptr++; *ptr = 115; 指针本来指向a的首地址,地址加1运算后,ptr指向了a相邻的高地址,造成内存越界。
二维数组
int a [2][3]={0}; 内存中是按行线性存储的:a[0][0]...a[1][2]
a[0] 、b[0][0] 表示数组的第一个元素
a、&a[0]、&b[0][0] 表示数组的首地址char*与char[]定义的区别
在C中定义字符串有下列几种形式:字符串常量,char数组,char指针
#define s1 "this is s1"
char* s2=”abc”;
char s3[] =”cde”;
本质区别
1)当定义char a[10]时,编译器会给数组分配十个单元,每个单元的数据类型为字符,sizeof(a) = 10
2)而定义char *s 时,这是给指针变量,只占四个字节,32位,用来保存一个地址。sizeof(s) = 4
指令预处理
替代表达式:#define GET_MAX(a,b)((a)>(b))?(a):(b) 推荐用函数
这种替换容易造成陷进:
GET_MAX(left++,right++) ((a++)>(b++))?(a++):(b++) 导致自加了两次,和你预期的不一样了。
定义错误码: #define ERR_INPUT_NULL 0xF7104060 推荐使用枚举
替换指针函数 (便于阅读,简化重复代码)
#define DECLARE_FUNC(func) func* pfn ## func
#define EXTERN_DECLARE_FUNC(func) extern func* pfn ## func
替换调用指针函数(便于阅读,简化重复代码)
#define CALL_FUNC(ret, func, ...) \
ret = MY_PFN_PREFIX pfn ## func(__VA_ARGS__); \
条件编译
#if(大字节序列)
#else
#endif
#ifndef _H_ (防止重复引用头文件)
#define _H_
#endif
#pragma pack(2) 2字节对齐
位运算(位域)
有些信息在存储时不需要占用一个完整的字节,只要占几个或一个二进制位。位域(在结构体定义时,我们可以指定某个成员变量所占用的二进制位数)就是把一个字节中的二进制划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中安域名进行操作(要注意大小字节序)
typedef struct {
int userIdMask :1;
int statusMask :4;
} UserInfo_Mask_S a = { 0x1, 0xE};
C语言标准规定,位域的宽度不能超过它所依附的数据类型的长度。
基础数据结构
字符串操作(标准库、解析、匹配等)
线性表(含数组、动态数组等)
队列
栈
链表
哈希表
高阶数据结构
二叉查找树,平衡数
堆,二叉堆
图论,无向图、有向图等基本知识
常用的算法及思想
排序算法(快熟、插入、堆排序等)
迭代、递归的思想
分治的思想(如:二分查找、归并排序等)
搜索算法(深搜、广搜等)
贪心算法
动态规划