结构体、共用体、Makefile

一、结构体

1.1 结构体变量的初始化和赋值的方式

struct Student{int id;char name[32];int score;
}
struct Student s;
s.id = 1001;
strcpy(s.name,"zhangsan");
s.score = 98;
struct Student{int id;char name[32];int score;
}s;
s.id = 1001;
strcpy(s.name,"zhangsan");
s.score = 98;
struct Student{int id;char name[32];int score;
};
struct Struct s = {1001,"zhangsan",98};
struct Student{int id;char name[32];int score;
}s = {1001,"zhangsan",98};
struct Student{int id;char name[32];int score;
};
struct Student s={.id = 1001,.score = 98;
};
struct Student{int id;char name[32];int score;
};
struct Student s;
s = (struct Student){1001,"zhangsan",98};

1.2 结构体数组的初始化和赋值的方式

struct Student{int id;char name[32];int score;
};struct Student s[2];
s[1].id = 1001;
strcpy(s[1].name,"zhangsan");
s[1].score = 100;s[2].id = 1002;
strcpy(s[2].name,"lisi");
s[1].score = 101;
struct Student{int id;char name[32];int score;
};
struct Student s[2]={{1001,"zhangsan",98},{1002,"lisi",99}
};
struct Student{int id;char name[32];int score;
};
struct Student s[5] = {[0] = {1001,"zhangsan",98},[3] = {1002,"lisi",100}
};
struct Student{int id;char name[32];int score;
};
struct Struct s[5] = {[0] = {.id = 1001;.score = 99},[3] = {.name = "wangwu"}
};

1.3 C语言的结构体中不允许定义函数

C++的结构体中允许定义函数,但是C语言中不允许,C语言的结构体中可以有函数指针

#include <stdio.h>int my_add(int x,int y){return x+y;
}typedef struct Test{int id;char name[32];int score;int (*p)(int ,int );//定义函数指针
}Test_t;int main(int argc, const char *argv[])
{Test_t t;t.p = my_add;//让函数指针指向函数printf("%d\n",t.p(20,30));//通过函数指针调用函数return 0;
}
结果:
50

1.4 结构体对齐

----------------------------------32位系统------------------------------------------------

64位系统想将程序按32位编译,需要加编译选项 -m32

对齐规则:

1.如果结构体成员都是小于4字节,则按最大成员对齐

2.如果结构体有成员大于等于4字节,都按4字节对齐

3.要特别注意 char 和 short 连续存储问题:

每个成员距离首地址的偏移量必须是成员类型大小的整数倍!!

struct Test{char a;char b;char c;
}; 
共占3字节
struct Test{short b;char a;
};
共占4字节
struct Test{short b;char a;char c;
};
共占4字节
struct Test{char c;short b;char a;
};
共占6字节
struct Test{char c;int a;char b;
};
共占12字节
struct Test{char a;int c;
};
共占8字节
struct Test{char c;long long a;
};
共占12位

struct Test{char a;char b;short c;int d;
};
共占8字节
struct Test{char a;short c;char b;int d;
};
共占12字节

---------------------------------------64位系统--------------------------------------------

64位系统的对齐规则基本和32位系统一样,

只不过不是4位对齐,而是按照最大成员进行对齐

且每个成员距离首地址的偏移量也必须是成员类型大小的整数倍!!

struct Test{char a;long double b;
};
共占32字节
struct Test{char a;int b;char c;short d;long double e;
};
共占32字节

结构体中嵌套结构体时的对齐规则:

struct A{short x;short y;short z;
};
struct B{struct A m;char n;int k;
};

结构体A自身是2字节对齐,当把A放在B中的时候,由于B是4字节对齐的

相当于B为了满足自身的对齐,需要额外分给A两个字节(下图左紫色部分)

这两个字节是属于B的,所以B的成员可以占用

struct C{int x;short y;
};
struct D{struct C m;char n;int k;
};

结构体C自身就是4字节对齐,当把C放在D中的时候,D并没有为了满足自身的对齐,

而额外给C分配空间,因为C满足自身对齐时本来就浪费了两个字节(上图右紫色部分)

这两个字节时属于C的,所以D成员不可以占用

1.5 结构体位域

压缩结构体的一种手段,嵌入式底层开发时经常用到

#include <stdio.h>struct LED{unsigned char led0:1;unsigned char led1:1;unsigned char led2:1;unsigned char led3:1;unsigned char led4:1;unsigned char led5:1;unsigned char led6:1;unsigned char led7:1;
};int main(int argc, const char *argv[])
{printf("%ld\n",sizeof(struct LED));//8字节struct LED my_led;//点亮3号灯my_led.led3 = 1;//熄灭4号灯my_led.led4 = 0;//压缩之后成员的存储范围也随之变小了my_led.led5 = 2;//超范围了printf("%d\n",my_led.led5);//0return 0;
}
结果:
1
0

二、共用体(联合体)--union

1.定义共用体类型的格式以及使用共用体定义变量的格式,都和结构体一模一样,只不过把关键字struct 换成了union

2.共用体中的所有成员时共用同一块内存空间

3.共用体的所有成员首地址相同

4.共用体的大小取决于共用体中成员的最大类型

union 共用体类型名{数据类型1 成员1;数据类型2 成员2;...数据类型n 成员n
};

因为共用体中所有成员都是用同一块内存空间

修改一个成员 其他成员的值也会受影响

所以,使用共用体时,我们不会同时使用多个成员

#include <stdio.h>union Test{char a;short b;int c;long long d;
};int main(int argc, const char *argv[])
{printf("%ld\n",sizeof(union Test));//8union Test t;t.a = 100;printf("t.a = %d\n",t.a);t.b = 300;printf("t.b = %d\n",t.b);printf("t.a = %d\n",t.a);//成员首地址都是一样的printf("%p\n",&t.a);printf("%p\n",&t.b);printf("%p\n",&t.c);printf("%p\n",&t.d);return 0;
}
结果:
8
t.a = 100
t.b = 300
t.a = 44
0x7ffcdcbc8800
0x7ffcdcbc8800
0x7ffcdcbc8800
0x7ffcdcbc8800

#include <stdio.h>union Test{char a;int  d;
};int main(int argc, const char *argv[])
{union Test t;t.d = 0x12345678;if(t.a == 0x78){printf("小端\n");}else if(t.a == 0x12){printf("大端\n");}return 0;
}
结果:
小端

三、Makefile

3.1 什么是Makefile?

Makefile就是一个文件,他能体现出我们是否具有大型项目开发的能力

Makefile文件中存放的是整个项目编译的规则

它可以根据文件的时间戳来决定哪些文件需要重新编译(更新时间戳)

3.2 什么时Make?

make是一个可执行文件 是/usr/bin/make,是用来解析Makefile文件的,如果系统没有make,可以自己安装 sudo apt-get install make

3.3 Makefile 的语法

3.3.1 标签式语法

标签:		#标签必须顶满格写指令	#指令必须以 tab 键开头
标签1:指令1
标签2:指令2
...
标签n:指令n

执行时,直接使用make 命令即可

make 会在当前路径下,去自动寻找。名为Makefile 的文件来解析和执行

make 默认执行时 执行第一个标签下的内容

也可以使用 make 标签名 方式来指定执行哪个标签下的内容

如果文件名不叫Makefile或者makefile ,也可以使用 make -f 文件名 方式来指定解析哪些文件

3.3.2 目标:依赖 式语法

目标:依赖	#目标必须顶满格写指令	#指令必须以tab键开头
app:02test.cgcc 02test.c -o app

例如:

test.c

编译步骤:预处理 编译 汇编 链接

预处理: 展开头文件 删除注释 替换宏定义

gcc -E test.c -o test.i

编译:词法分析 语法分析 查错

gcc -S test.i -o test.s

汇编:将汇编文件生成二进制的文件

gcc -c test.s -o test.o

链接:链接多个目标文件和库文件 生成最终的可执行文件

gcc test.o -o app

以上流程为例,写Makefile来看Makefile的执行方式

app:test.ogcc test.o -o app
test.o:test.sgcc test.s -c -o test.o
test.s:test.igcc test.i -S -o test.s
test.i:test.cgcc test.c -E -o test.i

make在解析Makefile时,会进行自动推导

app-->依赖-->test.o-->依赖-->test.s-->依赖-->test.i-->依赖-->test.c

c i s o

所以最终执行的顺序:

gcc -E test.c -o test.i

gcc -S test.i -o test.s

gcc -c test.s -o test.o

gcc test.o -o app

Makefile的目标又分为 目标和伪目标

目标:最终执行完后会生成目标文件的 如app

伪目标:最终执行完后不会生成目标文件的 如clean

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

模拟大型项目,使用Makefile编写规则来编译项目

---------------(例子在最后)--------------------

Makefile中使用变量的方式和shell类似

VALUE = xxx

引用变量的值

$(VALUE) 或者 ${变量名}

变量的赋值方式:

这种赋值方式会将变量在整个文件中所有的赋值位置都找到
最后一次赋值的结果取出 赋给其他变量
V1=hello
V2=$(V1)
V1=world
all:@echo $(V2) //world
//@表示取消命令的回显
V1=hello
V2:=$(V1)
V1=world
all:@echo $(V2) //hello
V1=hello
V2=world
V1+=$(V2)
all:@echo $(V1) //hello world
如果前面已经给变量赋值过了,本次赋值不再生效
V1?=hello
V1?=world //赋值不生效
all:@echo $(V1) //hello

3.5 Makefile中的特殊变量

$@ 目标文件

$^ 所有依赖文件

$< 第一个依赖文件

CC=gcc
OBJ=main.o hqyj1.o hqyj2.o hqyj3.o
TARGET=app
INCLUDE=-I ../include
FLAG=-c -o$(TARGET):$(OBJ)$(CC) $^ -o $@
main.o:main.c$(CC) $(INCLUDE) $< $(FLAG) $@
hqyj1.o:hqyj1.c$(CC) $(INCLUDE) $< $(FLAG) $@
hqyj2.o:hqyj2.c$(CC) $(INCLUDE) $< $(FLAG) $@
hqyj3.o:hqyj3.c$(CC) $(INCLUDE) $< $(FLAG) $@clean:rm $(OBJ) $(TARGET)

3.6 Makefile 中的通配符

* Makefile中执行shell命令时使用的通配符 ( 通配任意长度的任意字符 )

LIST=$(shell ls *.c)
all:@echo $(LIST)

% Makefile中的通配符 ( 通配任意长度的任意字符 )

3.7 可以在Makefile包含其他的.mk文件

-include 要包含的文件名

-include ../config.mk

表示将上一级路径下的config.mk文件中的内容包含到当前Makefile文件中

---------------------------Makefile例子-------------------------------------

app:main.o hqyj1.o hqyj2.o hqyj3.ogcc main.o hqyj1.o hqyj2.o hqyj3.o -o app
main.o:main.cgcc -I ../include main.c -c -o main.o
hqyj1.o:hqyj1.cgcc -I ../include hqyj1.c -c -o hqyj1.o
hqyj2.o:hqyj2.cgcc -I ../include hqyj2.c -c -o hqyj2.o
hqyj3.o:hqyj3.cgcc -I ../include hqyj3.c -c -o hqyj3.oclean:rm main.o hqyj1.o hqyj2.o hqyj3.o app
CC=gcc
OBJ=main.o hqyj1.o hqyj2.o hqyj3.o
TARGET=app
INCLUDE=-I ../include
FLAG=-c -o$(TARGET):$(OBJ)$(CC) $(OBJ) -o $(TARGET)
main.o:main.c$(CC) $(INCLUDE) main.c $(FLAG) main.o
hqyj1.o:hqyj1.c$(CC) $(INCLUDE) hqyj1.c $(FLAG) hqyj1.o
hqyj2.o:hqyj2.c$(CC) $(INCLUDE) hqyj2.c $(FLAG) hqyj2.o
hqyj3.o:hqyj3.c$(CC) $(INCLUDE) hqyj3.c $(FLAG) hqyj3.oclean:rm $(OBJ) $(TARGET)
CC=gcc
OBJ=main.o hqyj1.o hqyj2.o hqyj3.o
TARGET=app
INCLUDE=-I ../include
FLAG=-c -o$(TARGET):$(OBJ)$(CC) $^ -o $@
main.o:main.c$(CC) $(INCLUDE) $< $(FLAG) $@
hqyj1.o:hqyj1.c$(CC) $(INCLUDE) $< $(FLAG) $@
hqyj2.o:hqyj2.c$(CC) $(INCLUDE) $< $(FLAG) $@
hqyj3.o:hqyj3.c$(CC) $(INCLUDE) $< $(FLAG) $@clean:rm $(OBJ) $(TARGET)
CC=gcc
OBJ=main.o hqyj1.o hqyj2.o hqyj3.o
TARGET=app
INCLUDE=-I ../include
FLAG=-c -o$(TARGET):$(OBJ)$(CC) $^ -o $@
%.o:%.c$(CC) $(INCLUDE) $< $(FLAG) $@clean:rm $(OBJ) $(TARGET)
-include ../config.mk 
OBJ=main.o hqyj1.o hqyj2.o hqyj3.o
TARGET=app$(TARGET):$(OBJ)$(CC) $^ -o $@
%.o:%.c$(CC) $(INCLUDE) $< $(FLAG) $@clean:rm $(OBJ) $(TARGET)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146352.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

数据清洗与预处理:从网页中提取的数据处理技术

目录 引言 一、数据清洗与预处理概述 1.1 数据清洗的定义 1.2 数据清洗的重要性 二、数据清洗与预处理的步骤 2.1 数据获取 2.2 数据去重 2.3 缺失值处理 2.4 异常值处理 2.5 数据格式化与标准化 2.6 数据转换与编码 2.7 数据整合与关联 2.8 数据可视化 三、技术…

C++11——function与bind

包装器 function包装器function的介绍function的使用function的使用场景function的意义 bind包装器bind的介绍bind的使用 function包装器 function的介绍 function是用来包装函数的&#xff0c;所以叫做包装器或者适配器&#xff0c;fuction的本质其实是一个类模板。 functio…

基于多域名,通过云运营商弹性负载,Nginx配置等基于的多租户系统部署

已经开发好久的系统&#xff0c;因为业务上没有需求&#xff0c;没有做上线部署&#xff0c;此系统为多租户系统&#xff0c;原来设计是通过租户码参数来识别的&#xff0c;每个租户访问&#xff0c;需要传自己的码过来&#xff0c;才能确定是哪个租户登录系统&#xff0c; 今…

数据结构和算法之树形结构(1)

文章出处: 数据结构和算法之树形结构(1) 关注码农爱刷题&#xff0c;看更多技术文章&#xff01;&#xff01; 树形结构是数据结构四种逻辑结构之一&#xff0c;也是被广泛使用的一种逻辑结构&#xff0c;它描述的是数据元素之间一对多的逻辑关系。树是一种非线性的数据结构&a…

SOMEIP_ETS_119: SD_Indicate_wrong_l4proto_param

测试目的&#xff1a; 验证DUT能够拒绝一个引用了带有错误l4proto参数&#xff08;既不是UDP也不是TCP&#xff09;的IPv4端点选项的SubscribeEventgroup消息&#xff0c;并以SubscribeEventgroupNAck作为响应。 描述 本测试用例旨在确保DUT遵循SOME/IP协议&#xff0c;当接…

基于单片机的智能电话控制系统设计

摘要&#xff1a; 为了能够使用电话实现电器设备的控制&#xff0c;文中通过单片机及双音多频解码集成电路&#xff0c;使用用 户通过电话输入相应的指令就能够实现远程设备的智能化控制。文章主要对系统的构成、软件及 硬件设计进行了简单的介绍&#xff0c;并且对其中的电路…

出现conda不是内部或外部命令,也不是可运行的程序或批处理文件。的解决办法

发现是我的环境变量不对&#xff0c;需要改成conda.exe所在的目录下 如果不知道自己conda.exe在哪的 可以下载个everything这个软件 找东西很快 找到后 点击环境变量-系统变量-Path-新建-&#xff08;你的conda.exe所在目录&#xff1a;绝对路径&#xff09; 完成上述操作…

Day4:杨辉三角

题目&#xff1a;给定一个非负整数numRows,生成杨辉三角的前numRows行。在杨辉三角中&#xff0c;每个数就是左上方和右上方数的和。 import java.util.ArrayList; import java.util.List;public class Test {public static List<List<Integer>> generate(int numR…

【学术会议征稿】2024年先进控制系统与自动化技术国际学术会议(ACSAT 2024)

2024年先进控制系统与自动化技术国际学术会议&#xff08;ACSAT 2024&#xff09; 2024 International Conference on Advanced Control Systems and Automation Technologies 2024年先进控制系统与自动化技术国际学术会议&#xff08;ACSAT 2024&#xff09;将于2024年11月15…

solidwork装配体取消零件固定

前面有固定导致零件移动不了 右键&#xff0c;找到浮动

Three.js 3D人物漫游项目(上)

本文目录 前言1、项目构建1.1 安装依赖1.2 初始化1.3 项目结构1.4 初始化的项目运行 2、加载模型2.1 threejs三要素2.1.1 代码解读 2.2 加载模型2.2.1 代码解读 2.3 效果 前言 在数字技术的浪潮中&#xff0c;三维图形渲染技术以其独特的魅力&#xff0c;正逐步渗透到我们生活的…

react hooks--useMemo

概述 相当于计算属性!!! useMemo实际的目的也是为了进行性能的优化。 ◼ 如何进行性能的优化呢&#xff1f;  useMemo返回的也是一个 memoized&#xff08;记忆的&#xff09; 值&#xff1b;  在依赖不变的情况下&#xff0c;多次定义的时候&#xff0c;返回的值是相同…

后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0920)

十三、文章分类页面 - [element-plus 表格] Git仓库&#xff1a;https://gitee.com/msyycn/vue3-hei-ma.git 基本架子 - PageContainer 功能需求说明&#xff1a; 基本架子-PageContainer封装文章分类渲染 & loading处理文章分类添加编辑[element-plus弹层]文章分类删除…

k8s中的微服务

目录 一、什么是微服务 二、微服务的类型 三、IPVS模式 1、ipvs模式配置方式 &#xff08;1&#xff09;在所有节点中安装ipvsadm &#xff08;2&#xff09;修改master节点的代理配置 &#xff08;3&#xff09;重启pod 四、微服务类型详解 1、clusterip 示例&#…

Flink提交任务

第3章 Flink部署 3.1 集群角色 3.2 Flink集群搭建 3.2.1 集群启动 0&#xff09;集群规划 表3-1 集群角色分配 具体安装部署步骤如下&#xff1a; 1&#xff09;下载并解压安装包 &#xff08;1&#xff09;下载安装包flink-1.17.0-bin-scala_2.12.tgz&#xff0c;将该jar包…

有什么兼容macOS 15 Sequoia系统的加密软件?

前言&#xff1a;近日&#xff0c;苹果更新了 macOS 15 Sequoia正式版&#xff0c;已经有用户在电脑上安装使用了。在这个信息化时代&#xff0c;系统一直在更新&#xff0c;运用一些工具时需要考虑兼容性。 刚有个客户来问迅软&#xff1a;你们迅软DSE客户端支持新发布的macO…

Linux 磁盘清理重新格式化挂载脚本及问题解决

Linux 磁盘清理重新格式化挂载脚本&#xff1a;diskformat.sh #!/bin/bash for i in {1…8} do umount /data0$i done PIDARRAY() for i in a b c d e f g h do parted -s /dev/sd i m k l a b e l g p t p a r t e d − s / d e v / s d i mklabel gpt parted -s /dev/sd im…

【高阶数据结构】二叉搜索树的插入、删除和查找(精美图解+完整代码)

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《高阶数据结构》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多《高阶数据结构》点击专栏链接查看&a…

【计算机网络篇】计算机网络概述

本文主要介绍计算机网络第一章节的内容&#xff0c;文中的内容是我认为的重点内容&#xff0c;并非所有。参考的教材是谢希仁老师编著的《计算机网络》第8版。跟学视频课为河南科技大学郑瑞娟老师所讲计网。 文章目录 &#x1f3af;一.计算机网络的组成 ✨主要内容 1.边缘部…

seL4 Capabilities(翻自官网)(一)

官网教程链接: Capability 初始化Capabilities tutorials // 先使用repo拉取一下tutorials&#xff0c;然后执行repo sync&#xff0c;所有的教程都在里面&#xff0c;学习某个的时候只需要改变的是 --tut 后面的参数 ./init --tut capabilities # building the tutorial exe…