C语言结构体

预处理,宏定义->编译指令
结构体,联合体,动态数据结构
逻辑运算符,递归函数

  • 预处理
    编译有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;
}```
- 递归原理
函数调用的过程中,函数体内又调用了自己,递归-栈
递推构造低阶规模

你可能感兴趣的:(C语言结构体)