嵌入式软件开发 day9(结构体,共用体,动态内存,编译过程)

小知识:

指针传参,最省开销

构造类型

一、结构体

1.1 结构体定义和使用

结构体描述:(注意:定义并不分配空间)

语法

有头结构体

struct  [结构体名]
{	
	数据类型   成员名1;
	数据类型   成员名2;
	……
	数据类型   成员名n;
}

无头结构体
注意:定义的时候一次性把,变量,指针,数组定义好

struct 
{

}a = {};

总结1:定义结构体时的关键字是struct,不可省略

总结3:结构体变量利用操作符 ‘’.’’ 访问成员

1.2 结构体成员引用

  • 结构体变量.成员名;

  • 指针->成员名;

1.3 结构体初始化及赋值

通过结构体创建变量的方式有三种:

  • struct 结构体名 变量名

  • #include <stdio.h>
    #include <stdlib.h>
    
    struct node_st
    {
    	int i;
    	float f;
    	char ch;
    };
    
    int main()
    {
    	struct node_st a;
    
    	a.i = 4;
    	a.f = 4.8;
    	a.ch = 'a';
    
    	printf("%d, %f, %c\n",a.i , a.f, a.ch);
    
    	exit(0);
    }
    
  • struct 结构体名 变量名 = { 成员1值 , 成员2值…}

  • #include <stdio.h>
    #include <stdlib.h>
    
    struct node_st
    {
    	int i;
    	float f;
    	char ch;
    };
    
    int main()
    {
    	struct node_st a = {4,8.9,'x'};
    
    	printf("%d, %f, %c\n",a.i , a.f, a.ch);
    
    	exit(0);
    }
    
  • 定义结构体时顺便创建变量

  • #include <stdio.h>
    #include <stdlib.h>
    
    struct node_st
    {
    	int i;
    	float f;
    	char ch;
    }a = {4,8.9,'x'};
    
    int main()
    {
    	printf("%d, %f, %c\n",a.i , a.f, a.ch);
    
    	exit(0);
    }
    

1.4 结构体嵌套定义

作用: 结构体中的成员可以是另一个结构体

#include <stdio.h>
#include <stdlib.h>

struct bith_st
{
	int year;
	int month;
	int day;
};

struct student_st
{
	char name[12];
	int age;
	struct bith_st bday;
	float math;
};

int main()
{
	struct student_st s1 = {"alan",20,{2021,7,26},98};

	printf("%s %d[%d-%d-%d] %f\n",s1.name, s1.age, s1.bday.year, s1.bday.month, s1.bday.day, s1.math);

	exit(0);
}

1.5 结构体类型指针

作用:通过指针访问结构体中的成员

  • 利用操作符 ->可以通过结构体指针访问结构体属性
#include <stdio.h>
#include <stdlib.h>

struct bith_st
{
	int year;
	int month;
	int day;
};

struct student_st
{
	char name[12];
	int age;
	struct bith_st bday;
	float math;
};

int main()
{
/*
	struct student_st s1 = {"alan",20,98},s2;
	struct student_st *p = &s1;

	// s2 = s1;

	printf("%s %d %f\n",s1.name, s1.age, s1.math);
	printf("%s %d %f\n",p->name, p->age, p->math);
*/

	struct student_st s1 = {"alan",20,{2021,7,26},98};
	struct student_st *p = &s1;

	printf("%s %d[%d-%d-%d] %f\n",p->name, p->age, p->bday.year, p->bday.month, p->bday.day, p->math);

	exit(0);
}

总结:结构体指针可以通过 -> 操作符 来访问结构体中的成员

1.6 结构体类型数组

作用:将自定义的结构体放入到数组中方便维护

语法struct 结构体名 数组名[元素个数] = { {} , {} , ... {} }

1.6.1 一维数组
#include <stdio.h>
#include <stdlib.h>

struct student_st
{
	char name[12];
	int age;
	float math;
};

int main()
{
	struct student_st s1[] = {{"alan",20,98}, {"lily",21,89}, {"john",22,99}};
	int i;
	struct student_st *p = s1;

	for(i = 0 ; i < sizeof(s1)/sizeof(*s1); i++)
		printf("%s %d %f\n",p[i].name, p[i].age, p[i].math);
//	printf("%s %d %f\n",p->name, p->age, p->math);

	exit(0);
}

1.6.2 二维数组
#include <stdio.h>
#include <stdlib.h>

struct student_st
{
	char name[12];
	int age;
	float math;
};

int main()
{
	struct student_st s1[2][3] = {{{"alan",20,98}, {"lily",21,89}, {"john",22,99}},{{"alan",20,98}, {"lily",21,89}, {"john",22,99}}};
	int i,j;
	struct student_st *p = *s1;

	struct student_st (*q)[3] = s1;

	for(i = 0 ; i < 2*3 ; i++)
		printf("%s %d %f\n",p[i].name, p[i].age, p[i].math);
	printf("\n");

	for(i = 0 ; i < 2; i++)
	{
		for(j = 0 ; j < 3; j++)
			printf("%s %d %f\n",q[i][j].name, q[i][j].age, q[i][j].math);
		printf("\n");
	}
//	printf("%s %d %f\n",p->name, p->age, p->math);

	exit(0);
}

1.7 地址对齐的概念

addr/sizeof()

对类型进行整除,对于不能整除的类型会加一偏移,直到能整除为止。

示例

#include <stdio.h>
#include <stdlib.h>


struct node_st
{
	int i;
	char ch[5];
	char ch1;
	float f;
};

int main()
{
	struct node_st a; //	= {4,'y',8.9,'x'};

	printf("%ld\n",sizeof(a));
/*
	printf("%p -> %d\n",&a.i, a.i);
	printf("%p -> %c\n",&a.ch, a.ch);
	printf("%p -> %f\n",&a.f, a.f);
	printf("%p -> %c\n",&a.ch1, a.ch1);
*/
	exit(0);
}

1.8 结构体做函数参数

#include <stdio.h>
#include <stdlib.h>

struct student_st
{
	char name[12];
	int age;
	float math;
};

func( struct student_st , struct student_st *, struct student_st, int , float , struct student_st * , char *, struct student_st (*)[3], struct student_st, struct student_st *){  ... }

int main()
{
	struct student_st s2;
	struct student_st *x = &s2;
	struct student_st s[3];
	struct student_st s1[2][3];
	struct student_st *p = s;
	struct student_st (*q)[3] = s1;


	func(s[0], p+1, *p , s[1].age, p[0].math, x , x->name , q+1 , *p , q[0])

	exit(0);
}

1.9 类型定义;(typedef)

作用:给一个已有类型取一个新名字

基本语法typedef [已有类型][新名字];

示例

struct student_st
{
	int id;
	char name[32];
	float math;
}

typedef struct student_st STU;

struct student_st s;
STU s;

暴力破解

将原类型中的名字进行位置替换

typedef int INT
INT i ; -> int INT ; -> int i;
------------------------------------------------------
typedef int ARR[3];				->int[3]  ARR;
ARR a,b;	-> int a[3],b[3];

typedef int ARR[2][3];			-> int[2][3]  ARR
ARR a;  ->  int a[2][3];
------------------------------------------------------
typedef int FUNC(int,int);		-> int(int,int)  FUNC
FUNC f; -> int f(int,int);

typedef int (*F)(int *,int*);		-> int(int*,int*) *    F
F  p; -> int (*p)(int *,int*);

typedef int *(*FUNC)(int*,int*);  ->int*(int*,int*) *   FUNC

typedef int *(*FUNC[3])(int*,int*);  -> int*(int*,int*) * [3]  FUNC
-----------------------------------------------------------
    
struct student_st
{
	int id;
	char name[32];
	float math;
}

typedef struct student_st STU;

struct student_st s;
STU s;

----------------------------

typedef struct student_st
{
    int id;
    char name[32];
    float math;
}STU,*STUP;             -> struct student_st STU;
  						-> struct student_st * STUP
STU s  -> struct student_st s;
STU *p -> struct student_st *p;
STUP p  -> struct student_st *p;

---------------------------------------------------------    

与#define的区别

  1. typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名。
  2. typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。
#define INT int
INT i;  ->  int i;

typedef int INT;
INT i;  ->  int i;
-------
#define INTP int *
INTP i,j;  ->  int *i,j;

typedef int *INTP;
INTP p,q;  -> int *p,*q;

二、共用体

1.1 共用体定义和使用

产生原因及类型描述:构造类型,定义并不分配空间

union [共用体名]
{	
	数据类型   成员名1;
	数据类型   成员名2;
	……
}

同一时刻,只有一个成员生效

1.2 所占内存空间

描述:分配最大成员的空间作为共用体的空间

1.3 成员引用

  • 共用体变量.成员名

  • 指针->成员名;

三、动态内存管理

3.1 malloc()

作用:动态申请内存,存放在堆上

描述:分配所需的内存空间,并返回一个指向它的指

void *malloc(size_t size)

3.2 free()

作用:释放内存

内存泄露

  1. 内存没释放
  2. 多次释放

注意:手动动态申请内存,需要手动释放

编译过程

预处理 编译 汇编 链接(动态库,静态库)

正常程序员编程时:

在编程时要考虑异常情况,会加上异常处理函数

gcc

选项含义后缀转换过程
-Egcc预处理c文件helloworld.c -> helloworld.i
-Sgcc编译c文件helloworld.i -> helloworld.s
-cgcc编译汇编helloworld.s -> helloworld.o
-ogcc链接可重定位文件\
-g保留单步调试信息文件,用gdb调试时调用
-Wallall warning 将编译过程中的隐藏警告打印出来\

深入了解 推荐:《编译原理》《链接器原理》

gcc预处理c文件
sudo gcc -E helloworld.c -o helloworld.i -v

在这里插入图片描述

gcc编译c文件
sudo gcc -S helloworld.i -o helloworld.s -v

在这里插入图片描述

gcc编译汇编
sudo gcc -C helloworld.s -o helloworld.o -v

在这里插入图片描述

gcc链接可重定位文件

gdb

调试工具

用法gdb filename

llist查看当前代码
l n跳转到第n行
rrun运行程序
bbreakpoint断点
b n在第n行设置断点
i breakpoints查看断点信息
nnext执行断点这条语句,一行行执行(不进入函数内部)
sstep进去函数内部执行
ccontinue继续跑,直到遇到下个断点为止
display [变量名,表达式]跟踪显示想要知道的信息
undisplay [序号]不显示这一条display

到达断点处时,断点这处还没执行

拓展:

1. typedef练习

void (*signal(int signo,void (*func)(int)))(int);
void (*  signal(int signo,void (*func)(int))  )  (int);
void(*)(int)    signal (int , void (*)(int) )
typedef void (*FUNCP)(int); 
FUNCP signal(int , FUNCP p);

qsort使用方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值