C语言基础

2019-10-11  本文已影响0人  山茶小树王勇军


软件生成

预编译、编译、汇编、链接

内存划分

代码段/数据段(初始化的全局变量、静态全局和局部变量)/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++)  \Rightarrow  ((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语言标准规定,位域的宽度不能超过它所依附的数据类型的长度。

基础数据结构

字符串操作(标准库、解析、匹配等)
线性表(含数组、动态数组等)
队列

链表
哈希表

高阶数据结构

二叉查找树,平衡数
堆,二叉堆
图论,无向图、有向图等基本知识

常用的算法及思想

排序算法(快熟、插入、堆排序等)
迭代、递归的思想
分治的思想(如:二分查找、归并排序等)
搜索算法(深搜、广搜等)
贪心算法
动态规划

上一篇下一篇

猜你喜欢

热点阅读