预处理,宏定义->编译指令
结构体,联合体,动态数据结构
逻辑运算符,递归函数
预处理
编译有4个步骤,.c文件->.i文件 预处理 ->.s文件 编译 -> .o文件 汇编 ->可执行文件 链接
gcc -o hello.i hello.c -E-E表示gcc只进行预处理
预处理的第一步是展开头文件
宏定义
#define R 10 定义宏,预处理的时候将宏直接替换,但是将R作为字符串10,然后后面比如int a = R;这里发生的是字符串替换,然后发生了类型转换,宏只是单纯的字符串替换。
#include
#define R 10
#define M int main(
M){
int a = R;
printf("a=%d\n",a);
printf("helloworld\n");
return 0;
}```
反复使用的常量和数组buffer的大小,为了便于修改,`int a[R];`因为不能用变量进行确定大小。
- 宏函数
`#define N(n) n*10 int b = N(a);`
宏替换在预处理阶段只是单纯的替换,而不会进行运算,所以注意四则运算的优先级
include
define R 10
define M int main(
define N(n) n*10
define ADD(a,b) (a+b)
M){
int a = R;
printf("a=%d\n",a);
printf("helloworld\n");
int b = N(a);
printf("b=%d\n",b);
int c = ADD(a,b) * ADD(a,b);
printf("c=%d\n",c);
return 0;
}```
typedef
给变量类型起别名,typedef int tni;是C语句,typedef int* p;
通常对自定义的数据类型起别名,size_t其实是typedef unsigned long size_t;
作用域是在大括号里面,但是宏定义是在整个代码文件中都是起作用的。
结构体的声明和定义
不同类型数据的集合,数组是相同数据类型的集合。
#include
struct weapon{
char name[20];
int atk;
int price;
}weapon_2;//声明和定义在一起,全局变量
//创建了结构体类型
struct{
char name[20];
int atk;
int price;
}weapon_3;//直接定义了变量,后面不能使用来定义新的变量
int main(){
//使用结构体类型声明一个变量
struct weapon weapon_1;//声明和定义分离的方法
return 0;
}```
- 结构体的初始化和引用
include
struct weapon{
char name[20];
int atk;
int price;
}weapon_2;//声明和定义在一起,全局变量
//创建了结构体类型
int main(){
//使用结构体类型声明一个变量
//初始化列表
struct weapon weapon_1={"weapon_name",100,200};//声明和定义分离的方法
printf("%s\n",weapon_1.name);
//结构体数组
struct weapon w[3]={"weapon_4"};//初始化时候需要指定9个常量
printf("%s\n",w[0].name);
return 0;
}```
结构体指针
#include
struct weapon{
char name[20];
int atk;
int price;
}weapon_2;//声明和定义在一起,全局变量
//创建了结构体类型
int main(){
//使用结构体类型声明一个变量
//初始化列表
struct weapon weapon_1={"weapon_name",100,200};//声明和定义分离的方法
printf("%s\n",weapon_1.name);
//结构体数组
struct weapon we[3]={{"weapon_4"},{"weapon_5"}};//初始化时候需要指定9个常量
printf("%s\n",we[0].name);
//结构体指针变量
struct weapon *w;
w = &weapon_1;
printf("name=%s\n",(*w).name);//使用w->name指向运算符来替换(*w).name
printf("name=%s\n",w->name);
//指向结构体数组
struct weapon *p;
p = we;
printf("%s\n",p->name);
p++;
printf("%s\n",p->name);
return 0;
}```
- 共用体
不同类型的变量共享同一块内存地址,结构体大小有一个字节对齐的概念。
include
union data{
int a;
char b;
int c;
};
struct data1{
int a;
char b;
int c;
};
int main(){
union data data_1;
data_1.b = 'C';
data_1.a = 10;
//b会被覆盖掉,共用体长度为最多的决定
printf("%lu\n",sizeof(struct data1)); //12
printf("%lu\n",sizeof(union data)); // 4
return 0;
}```
动态数据结构-静态链表
#include
struct weapon{
int price;
int atk;
struct weapon *next;
};
int main(){
struct weapon a,b,c,*head;
a.price = 100;
a.atk = 100;
b.price = 200;
b.atk = 200;
c.price = 300;
c.atk = 300;
head = &a;
a.next = &b;
b.next = &c;
c.next = NULL;
struct weapon *p;
p = head;
while(p){
printf("%d,%d\n",p->atk,p->price);
p = p->next;
}
return 0;
}```
- 动态链表
include
include
struct weapon{
int price;
int atk;
struct weapon next;
};
struct weapon create(){
//定义3个指针变量
struct weapon head;
struct weapon p1,p2;
int n = 0;
//开辟内存
p1 = p2 = (struct weapon)malloc(sizeof(struct weapon));//分配内存
scanf("%d,%d",&p1->price,&p1->atk);
head = NULL;
while(p1->price != 0){
n++;//元素个数加1
if(n==1){
head = p1;
}else{
p2->next = p1;
}
p2 = p1;
p1 = (struct weapon*)malloc(sizeof(struct weapon));
scanf("%d,%d",&p1->price,&p1->atk);
}
p2->next = NULL;
return head;
}
int main(){
struct weapon *p;
p = create();
while(p){
printf("%d,%d\n",p->price,p->atk);
p = p->next;
}
return 0;
}```
按位与
& | ^ ~ << >>
作用,迅速清零,a&0,保留指定位置,a&128,判断奇偶,a&1
#include
int main(){
int a = 4;
int b = 7;
int c = a&b; //4
printf("%d\n",c);
return 0;
}```
- 按位或
设定数据的指定位置,`a|0xFF`
include
int main(){
int a = 9;// 00001001
int b = 5;// 00000101
int c = a|b;// 00001101
printf("%d\n",c);
return 0;
}```
按位异或
异或,相异才是1,定位翻转,a^0xFF,数值交换a=a^b;b=b^a;a=a^b;
#include
int main(){
int a = 9;//00001001
int b = 5;//00000101
int c = a^b;//00001100
printf("%d\n",c);
return 0;
}```
- 左移右移
将数据对应的二进制值左移或者右移几位
include
int main(){
int a = 3;
a = a << 4;
printf("%d\n",a);
return 0;
}```
左移几位就相当于乘以2n,右移就是除以2n,如果有符号最高位不会变化,右移符号位是1,就会补1,乘法运算的话用左移就会速度更快。
递归调用
递归会牺牲效率
#include
//求阶乘
int jiecheng(int n){
if(n<0){
printf("error\n");
return -1;
}
if(n==1){
return 1;
}
return n*jiecheng(n-1);
}
int main(){
int n;
printf("please input n\n");
scanf("%d",&n);
int result;
result = jiecheng(n);
printf("%d\n",result);
return 0;
}```
- 递归原理
函数调用的过程中,函数体内又调用了自己,递归-栈
递推构造低阶规模