ARM Study Day10:标准C之结构体、联合、枚举

一、有参宏定义
在这里插入图片描述

#include <stdio.h>
#define PRINT(N)  printf(#N"=%d\n", N) //定义打印整形术的宏函数
#define ID(N)   id##N     
int main(void)
{
        int a = 20 , b = 30;

        PRINT(a); //替换结果:printf("a""=%d\n",a)等价于 printf("a = %d\n", a);
        PRINT(b); //替换结果:printf("b""=%d\n",b)等价于 printf("a = % d\n", b);

        //先把宏值中的参数N用1,2替换,替换之后将id##1/2前后粘连,结果就是id1、id然后吧ID宏名用id1、id2替换
        int ID(1) = 100, ID(2) = 200;  //替换结果:int id1=100;id2=200;
        printf("%d, %d\n", ID(1), ID(2));  //替换结果:printf(“%d %d,id1,id2”);
        return 0;
}

在这里插入图片描述

#include <stdio.h>
#define PRINT(N)  printf(#N"=%d\n", N) //定义打印整形术的宏函数
#define ID(N)   id##N     
#define PI (3.1415926)
int main(void)
{
        int a = 20 , b = 30;

        PRINT(a); //替换结果:printf("a""=%d\n",a)等价于 printf("a = %d\n", a);
        PRINT(b); //替换结果:printf("b""=%d\n",b)等价于 printf("a = % d\n", b);

        //先把宏值中的参数N用1,2替换,替换之后将id##1/2前后粘连,结果就是id1、id然后吧ID宏名用id1、id2替换
        int ID(1) = 100, ID(2) = 200;  //替换结果:int id1=100;id2=200;
        printf("%d, %d\n", ID(1), ID(2));  //替换结果:printf(“%d %d,id1,id2”);

        //优秀代码:如果将来3.14精度不够,只需修改宏PI的值即可,将来预处理阶段自动替换

        double r = 10;
        printf("面积: %lf\n",PI*r*r);
        //$undef PI  //取消PI定义
        printf("周长:%lf\n",PI*2*r);
        //预定义宏演示:注意:前后都是两个下划线
        int *p = NULL;
        if (!p)
        {
                printf("这是一个非法的指针不允许访问:%s, %s, %s, %s, %d\n",
                __DATE__, __TIME__,__FILE__,__FUNCTION__,__LINE__);  //将来软件调试的LOG日志
                return -1;
        }
        return 0;
}

//gcc的-D选项的妙用,通过-D选项可以给程序传递常量宏
//gcc -DSIZE=5 -DEND=\"TARENA\"  -o define define.c



#include <stdio.h>
int main(void)
{
        int a[SIZE]={0};

        //初始化数组
        for(int i = 0; i < SIZE; i++)
                a[i] = i + 1;

        //打印数组
        for(int i = 0; i < SIZE ;i++)
                printf("%d ", a[i]);
        printf("\n");

        printf("%s\n", END);
        return 0;
}

在这里插入图片描述
在这里插入图片描述

//条件编译预处理指令
#include <stdio.h>
int main(void)
{
	//#if演示
	//编译命令:gcc -E -o if.i if.c;vim if.i;gcc -o if if.i; ./if
	//编译命令:gcc -DA=1 -E -o if.i if.c; vim if.i; gcc -o if if.i; ./if
#if A == 1
	printf("1.\n");
#endif  //和#if配对
	//#if.....#else演示
	//编译命令:gcc -E -o if.i if.c; vim if.i;gcc -o if if.i; ./if
	//编译命令:gcc -DB=1 -E -o if.i if.c; vim if.i;gcc -o if if.i; ./if
#if B==1
	printf("2.\n");
#else 
	printf("3.\n");
#endif
	//#ifdef或者#ifndef...#else演示
	//编译命令:gcc -E -o if.i if.c; vim if.i;gcc -o if if.i; ./if
	//编译命令:gcc -DC -E -o if.i ;vim if.i ;gcc -o if if.i; ./if
//#ifdef C
#ifndef C
	printf("4.\n");
#else //可以不加
	printf("5.\n");
#endif
	//#if defined....#else
	//编译命令:gcc -E -o if.i if.c; vim if.i ; if -o if if.i; ./if
	//编译命令:gcc -DD -E -o if.i if.c; vim if.i ; if -o if if.i; ./if
	//编译命令:gcc -DE -E -o if.i if.c; vim if.i ; if -o if if.i; ./if
	//编译命令:gcc -DD -DE -E -o if.i if.c; vim if.i ;gcc -o if if.i; ./if
	//编译命令:gcc -DE -DD -E -o if.i if.c; vim if.i ; if -o if if.i; ./if
	
#if defined(D)
	printf("6.\n");
#elif !defined(D) && !defined(E)
	printf("7.\n");
#else
	printf("8.\n");
#endif
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

复合类型与高级指针

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//结构体玩法1:直接定义结构体变量(很少用)
#include <stdio.h>
#include <string.h>

int main(void)
{
        //直接定义结构体变量stul并且初始化
        struct
        {
                char name[32];
                int age;
        }stu1 = {"feifei",18};
        //打印学生信息
        printf("%s, %d\n",stu1.name, stu1.age);

        stu1.age++;
        strcpy(stu1.name, "feifeiya");
        //
        printf("%s, %d\n", stu1.name, stu1.age);
        return 0;

}


//结构体玩法2:先声明一个结构体变量(好比自己做一个自信的 int类型)
//然后用结构类型定义变量分配内容

#include<stdio.h>
#include<string.h>

//先声明结构体类型描述学生的信息,类似造一个自己的int类型一样

struct student{
        char name[32];
        int age;
        };//好比把Struct student当成Int类型来看

int main(void)
{
        //用自己造的结构体类型定义结构体变量分配内存转储学生信息
        //struct student stu1 = {"feifei",18};
        struct student stu1 = {.age = 18,.name = "feifei"};

        printf("%s, %d\n",stu1.name, stu1.age);

        stu1.age++;
        strcpy(stu1.name, "feifeiya");

        printf("%s, %d\n",stu1.name, stu1.age);

        struct student *pstu = &stu1;

        printf("%s, %d\n", pstu->name, pstu->age);
        pstu->age++;
        strcpy(pstu->name,"feifei");
        printf("%s, %d\n", pstu->name, pstu->age);
        return 0;
}

在这里插入图片描述
在这里插入图片描述

//结构体数据的玩法3:数组中每个成员是一个结构体
#include <stdio.h>
//声明结构体类型来描述学生信息
struct student{
        char name[32];
        int age;
};

//后给声明的结构体函数取别名
typedef struct student stu_t; //给struct student取别名叫stu_t,好比把stu_t当成Int来看

int main(void)
{
        //定义初始化三个学生信息
        stu_t stu_info[3] = {
                {.name = "刘备", .age = 20},
                {.name = "关于", .age = 19},
                {.name = "张飞", .age = 18},
        };
        int len = sizeof(stu_info)/sizeof(stu_info[0]);//换算元素个数
        //打印
        for(int i = 0; i < len ;i++)
                printf("%s, %d\n", stu_info[i].name, stu_info[i].age);
        for(int i = 0; i < len ;i++)
                printf("%s, %d\n", stu_info[i].name, stu_info[i].age);
        for(int i = 0; i < len ;i++)
                printf("%s, %d\n", stu_info[i].name, stu_info[i].age);
        return 0;
}

```c
//结构体作为函数的形参和返回值
//切记:以后函数操作结构体,函数的形参一律是结构体指针
#include <stdio.h>
//声明结构体类型描述学生信息并且取别名
typedef struct {
	char name[32];
	int age;
}stu_t;

void show(stu_t st){ //st=stu=内存拷贝自己
	printf("%s, %d\n", st.name, st.age);
}

void grow(stu_t st){ //st=stu=内存拷贝自己
	st.age++;  //仅仅修改了形参st.age,并没有修改实参stu.age
}

void show1(stu_t *pst){  //pst=&stu.pst指向实参
	printf("%s, %d\n", pst->name, pst->age);
}
void grow1(stu_t *pst)	{ //pst=&stu
	pst->age++;     //直接修改实参stu.age
}
//定义返回学生信息数的函数

stu_t return_stu(void){
	stu_t stu = {"张三", 20};
	return stu;   //返回结构体变量的值
}

stu_t *return_pstu(void){
	stu_t stu = {"张三", 20};
	return &stu;  //不能返回局部结构体变量的指针
}
	

int main(void)
{
	stu_t stu = {"feifei", 15};
	show(stu); //传递实参结构体stu
	grow(stu); //传递实参结构体stu
	show(stu); //传递实参结构体stu
	show1(&stu); //传递实参结构体stu的地址
	grow1(&stu);
	show1(&stu);
	stu_t stu2 = return_stu();
	printf("%s, %d\n", stu2.name, stu2.age);
	stu_t *pstu = return_pstu();
	printf("%s, %d\n",pstu->name,pstu->age);
	return 0;
}

![在这里插入图片描述](https://img-blog.csdnimg.cn/cee46535f5634d37b4a2f3e20f914329.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASnVzdE1vbmlrYWE=,size_20,color_FFFFFF,t_70,g_se,x_16)

```c
#include <stdio.h>
//声明描述学生出生日期的结构体变量
typedef struct birthday{
        int year;
        int month;
        int day;
}birth_t;

//声明描述学生信息的结构体类型
typedef struct student{
        char name[32];
        int age;
        birth_t birth;
}stu_t;
int main(void)
{
        stu_t stu1 = {.birth = {.year = 2002, .month = 2, .day = 2}, .name = "shabi", .age = 18};
        stu_t *pstu = &stu1;

        printf("%s, %d, %d-%d-%d\n", stu1.name, stu1.age, stu1.birth.year, stu1.birth.month, stu1.birth.day);
        printf("%s, %d, %d-%d-%d\n", pstu->name, pstu->age, pstu->birth.year, pstu->birth.month, pstu->birth.day);

        stu1.age++;
        pstu->birth.year = 2001;
        pstu->birth.month =3;

        printf("%s, %d, %d-%d-%d\n", stu1.name, stu1.age, stu1.birth.year, stu1.birth.month, stu1.birth.day);
        printf("%s, %d, %d-%d-%d\n", pstu->name, pstu->age, pstu->birth.year, pstu->birth.month, pstu->birth.day);

        return 0;
}

//结构体嵌套结构体变量
#include <stdio.h>
//声明描述学生出生日期的结构体变量
typedef struct birthday{
        int year;
        int month;
        int day;
}birth_t;
//声明描述学生信息的结构体类型
typedef struct student{
        char name[32];
        int age;
        birth_t *pbirth;        //嵌套birth_t结构体指针变量来存储学生的出生日期的信息
}stu_t;
int main(void)
{
        //stu_t stu1 = {"shabi", 18, NULL};  传统初始化
        stu_t stu1 = {.pbirth = NULL, .name = "shabi", .age = 18};
        stu_t *pstu = &stu1;
        //初始化pbirth成员让它指向有效的内容
        birth_t birth = {2002, 2, 2};  //定义初始化birth变量存储关于学生的出生日期
        stu1.pbirth = &birth;  //让pbirth指向birth
        //等价于pstu->pbirth = &birth;
        //打印
        printf("%s, %d, %d-%d-%d\n", stu1.name, stu1.age, stu1.pbirth->year, stu1.pbirth->month, stu1.pbirth->day);
        printf("%s, %d, %d-%d-%d\n", pstu->name, pstu->age, pstu->pbirth->year, pstu->pbirth->month, pstu->pbirth->day);
        //修改
        stu1.age++;
        pstu->pbirth->year = 2001;
        pstu->pbirth->month =3;

        printf("%s, %d, %d-%d-%d\n", stu1.name, stu1.age, stu1.pbirth->year, stu1.pbirth->month, stu1.pbirth->day);
        printf("%s, %d, %d-%d-%d\n", pstu->name, pstu->age, pstu->pbirth->year, pstu->pbirth->month, pstu->pbirth->day);

        return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


 //结构体内存对齐和补齐
 #include <stdio.h>
 struct A{
     char buf[2];  //CCXX
     int a; //IIII
 };
 
 struct B{
     char c;  //CX
     short s[2];//SSSS
     int i;
 };
 #pragma pack(1)  //让gcc编译器强制从代码的这个位置开始往后所有代码>    按照1字节对齐方式

 struct C{
     char c;
    short s[2];
     int Ii;
 };
 #pragma pack()  //让gcc编译器从这里开始往后重新恢复到原先的补齐和对
      齐方式
 struct D{
     int i;
     char c;
 };

 struct E{
    double d;
    char c;
 };
 int main(void){
     printf("sizeof(struct A) = %lu\n", sizeof(struct A));
 printf("sizeof(struct B) = %lu\n", sizeof(struct B));
     printf("sizeof(struct C) = %lu\n", sizeof(struct C));
     printf("sizeof(struct D) = %lu\n", sizeof(struct D));
     printf("sizeof(struct E) = %lu\n", sizeof(struct E));
     return 0;
        }

在这里插入图片描述
在这里插入图片描述

//枚举类型演示
#include<stdio.h>
//声明枚举数据类型
enum Color{
        RED, //好比给0这个整形数字取了个别名叫RED
        GREEN, //好比给1这个这个整形数组取别名
        BLUE, //好比给2这个整形数字取别名叫BLACK
        BLACK = 10, //好比给10取别名叫BLACK
        WHITE,//好比给11取别名
};  //默认都是INT类型

int main(void){
        //单次显然比数字可读性好
        printf("%d, %d, %d, %d, %d\n", RED, GREEN, BLUE, BLACK, WHITE);
        return 0;
}

在这里插入代码片
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值