預(yù)處理,宏定義->編譯指令
結(jié)構(gòu)體,聯(lián)合體,動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)
邏輯運(yùn)算符,遞歸函數(shù)
- 預(yù)處理
編譯有4個(gè)步驟,.c文件->.i文件 預(yù)處理 ->.s文件 編譯 -> .o文件 匯編 ->可執(zhí)行文件 鏈接
gcc -o hello.i hello.c -E-E表示gcc只進(jìn)行預(yù)處理
預(yù)處理的第一步是展開(kāi)頭文件 - 宏定義
#define R 10定義宏,預(yù)處理的時(shí)候?qū)⒑曛苯犹鎿Q,但是將R作為字符串10,然后后面比如int a = R;這里發(fā)生的是字符串替換,然后發(fā)生了類型轉(zhuǎn)換,宏只是單純的字符串替換。
#include<stdio.h>
#define R 10
#define M int main(
M){
int a = R;
printf("a=%d\n",a);
printf("helloworld\n");
return 0;
}```
反復(fù)使用的常量和數(shù)組buffer的大小,為了便于修改,`int a[R];`因?yàn)椴荒苡米兞窟M(jìn)行確定大小。
- 宏函數(shù)
`#define N(n) n*10 int b = N(a);`
宏替換在預(yù)處理階段只是單純的替換,而不會(huì)進(jìn)行運(yùn)算,所以注意四則運(yùn)算的優(yōu)先級(jí)
include<stdio.h>
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語(yǔ)句,typedef int* p;
通常對(duì)自定義的數(shù)據(jù)類型起別名,size_t其實(shí)是typedef unsigned long size_t;
作用域是在大括號(hào)里面,但是宏定義是在整個(gè)代碼文件中都是起作用的。 - 結(jié)構(gòu)體的聲明和定義
不同類型數(shù)據(jù)的集合,數(shù)組是相同數(shù)據(jù)類型的集合。
#include<stdio.h>
struct weapon{
char name[20];
int atk;
int price;
}weapon_2;//聲明和定義在一起,全局變量
//創(chuàng)建了結(jié)構(gòu)體類型
struct{
char name[20];
int atk;
int price;
}weapon_3;//直接定義了變量,后面不能使用來(lái)定義新的變量
int main(){
//使用結(jié)構(gòu)體類型聲明一個(gè)變量
struct weapon weapon_1;//聲明和定義分離的方法
return 0;
}```
- 結(jié)構(gòu)體的初始化和引用
include<stdio.h>
struct weapon{
char name[20];
int atk;
int price;
}weapon_2;//聲明和定義在一起,全局變量
//創(chuàng)建了結(jié)構(gòu)體類型
int main(){
//使用結(jié)構(gòu)體類型聲明一個(gè)變量
//初始化列表
struct weapon weapon_1={"weapon_name",100,200};//聲明和定義分離的方法
printf("%s\n",weapon_1.name);
//結(jié)構(gòu)體數(shù)組
struct weapon w[3]={"weapon_4"};//初始化時(shí)候需要指定9個(gè)常量
printf("%s\n",w[0].name);
return 0;
}```
- 結(jié)構(gòu)體指針
#include<stdio.h>
struct weapon{
char name[20];
int atk;
int price;
}weapon_2;//聲明和定義在一起,全局變量
//創(chuàng)建了結(jié)構(gòu)體類型
int main(){
//使用結(jié)構(gòu)體類型聲明一個(gè)變量
//初始化列表
struct weapon weapon_1={"weapon_name",100,200};//聲明和定義分離的方法
printf("%s\n",weapon_1.name);
//結(jié)構(gòu)體數(shù)組
struct weapon we[3]={{"weapon_4"},{"weapon_5"}};//初始化時(shí)候需要指定9個(gè)常量
printf("%s\n",we[0].name);
//結(jié)構(gòu)體指針變量
struct weapon *w;
w = &weapon_1;
printf("name=%s\n",(*w).name);//使用w->name指向運(yùn)算符來(lái)替換(*w).name
printf("name=%s\n",w->name);
//指向結(jié)構(gòu)體數(shù)組
struct weapon *p;
p = we;
printf("%s\n",p->name);
p++;
printf("%s\n",p->name);
return 0;
}```
- 共用體
不同類型的變量共享同一塊內(nèi)存地址,結(jié)構(gòu)體大小有一個(gè)字節(jié)對(duì)齊的概念。
include<stdio.h>
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會(huì)被覆蓋掉,共用體長(zhǎng)度為最多的決定
printf("%lu\n",sizeof(struct data1)); //12
printf("%lu\n",sizeof(union data)); // 4
return 0;
}```
- 動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)-靜態(tài)鏈表
#include<stdio.h>
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;
}```
- 動(dòng)態(tài)鏈表
include<stdio.h>
include<stdlib.h>
struct weapon{
int price;
int atk;
struct weapon next;
};
struct weapon create(){
//定義3個(gè)指針變量
struct weapon head;
struct weapon p1,p2;
int n = 0;
//開(kāi)辟內(nèi)存
p1 = p2 = (struct weapon)malloc(sizeof(struct weapon));//分配內(nèi)存
scanf("%d,%d",&p1->price,&p1->atk);
head = NULL;
while(p1->price != 0){
n++;//元素個(gè)數(shù)加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<stdio.h>
int main(){
int a = 4;
int b = 7;
int c = a&b; //4
printf("%d\n",c);
return 0;
}```
- 按位或
設(shè)定數(shù)據(jù)的指定位置,`a|0xFF`
include<stdio.h>
int main(){
int a = 9;// 00001001
int b = 5;// 00000101
int c = a|b;// 00001101
printf("%d\n",c);
return 0;
}```
- 按位異或
異或,相異才是1,定位翻轉(zhuǎn),a^0xFF,數(shù)值交換a=a^b;b=b^a;a=a^b;
#include<stdio.h>
int main(){
int a = 9;//00001001
int b = 5;//00000101
int c = a^b;//00001100
printf("%d\n",c);
return 0;
}```
- 左移右移
將數(shù)據(jù)對(duì)應(yīng)的二進(jìn)制值左移或者右移幾位
include<stdio.h>
int main(){
int a = 3;
a = a << 4;
printf("%d\n",a);
return 0;
}```
左移幾位就相當(dāng)于乘以2n,右移就是除以2n,如果有符號(hào)最高位不會(huì)變化,右移符號(hào)位是1,就會(huì)補(bǔ)1,乘法運(yùn)算的話用左移就會(huì)速度更快。
- 遞歸調(diào)用
遞歸會(huì)犧牲效率
#include<stdio.h>
//求階乘
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;
}```
- 遞歸原理
函數(shù)調(diào)用的過(guò)程中,函數(shù)體內(nèi)又調(diào)用了自己,遞歸-棧
遞推構(gòu)造低階規(guī)模