深度解析Linux-C——结构体(初始化,结构体数组,结构体大小,位段操作,联合体,内存对齐,C的预处理,宏和带参宏,条件编译)

目录

结构体的三种初始化

结构体的两种引用

结构体数组

结构体大小

结构体实现位段操作

联合体

 内存对齐

C的预处理

 带参宏

 条件编译


结构体的三种初始化

定义如下结构体

struct  student 
{char name[100];  int age;  float  height;   
} ;

 1、定义变量时初始化

struct  student  xm = {"小明",18,175.3}

2、不按顺序的初始化

struct  student  xm ={.age=18, .height=175.3, .name="小明"};

3、在定义后初始化

struct  student  xm;
//xm.name = "小明"; // name是数组名是一个常量,常量不能赋值  
strcpy(xm.name,"小明");
xm.age = 18; 
xm.height=173.5;

 

结构体的两种引用

1、结构体变量是普通值时,使用变量名+  “   .   ”   访问

2、结构体变量是指针时,使用指针+   “   ->   ”   访问

结构体数组

定义:

struct student
{char name[1024]; // 姓名int id;          // 学号char clas[1024]; // 班级
};

初始化: 

struct student arry[50] = 
{{"小明", 1, "高一三班"},{"小东", 2, "高二三班"},{"小美", 3, "高三三班"},
};

 

结构体大小

结构体大小是根据 《最大的数据字节》对齐的原则进行分配的! 每次数据分配的空间都是《根据最大的字节数》进行对齐。

 参考:【C语言】结构体内存对齐_编译器默认对齐数-CSDN博客

结构体实现位段操作

位段操作允许程序员直接操作数据的特定位,而不是整个数据结构

从而在需要精确控制硬件或进行高效数据处理时非常有用。

 

带位段操作的结构体的大小

 

联合体

联合体的外在形式跟结构体非常类似,但它们有一个本质的区别:

结构体中的各个成员是各自独立的,而联合体中的各个成员却共用同一块内存,因此联合体也称为共用体。

整个联合体变量的尺寸,取决于联合体中尺寸最大的成员。

给联合体的某个成员赋值,会覆盖其他的成员,使它们失效。

联合体各成员之间形成一种“互斥”的逻辑,在某个时刻只有一个成员有效。

声明联合体:

union attr
{int x;char y;double z;  
};

定义联合体:

int main()
{// 定义联合体变量union attr n;
}// 普通初始化:第一个成员有效(即只有100是有效的,其余成员会被覆盖)
union attr at = {100, 'k', 3.14};// 指定成员初始化:最后一个成员有效(即只有3.14是有效的,其余成员会被覆盖)
union attr at = {.x  = 100,.y = 'k',.z = 3.14,
};

 联合体指针

union attr *p = &at;
p->x = 100;
p->y = 'k';
p->z = 3.14;  // 只有最后一个赋值的成员有效printf("%d\n", p->x);
printf("%c\n", p->y);
printf("%lf\n", p->z);

 内存对齐

1.修改一个数据的对齐原则 

char c __attribute__((aligned(32))); // 将变量 c 的值、内存对齐值设置为32   

attribute语法:
attribute 机制是GNU特定语法,属于C语言标准语法的扩展。
attribute 前后都是双下划线,aligned两边是双圆括号。
attribute 语句,出现在变量定义语句中的分号前面,变量标识符后面。
attribute 机制支持多种属性设置,其中 aligned 用来设置变量的 m 值属性。
一个变量的内存对齐值只能提升,不能降低,且只能为正的2的n次幂

2.不适用任何的对齐原则 ,直接以真实大小存储 

 __attribute__((packed));

内存对齐,是为了CPU 更高效率取读取,内存的资源进行处理。 修改空间虽然可以节省内存,但是会降低CPU的处理效率。
 

C的预处理

头文件:#include

定义宏:#define

取消宏:#undef

条件编译:#if、#ifdef、#ifndef、#else、#elif、#endif

显示错误:#error

修改当前文件名和行号:#line

向编译器传送特定指令:#progma

一个逻辑行只能出现一条预处理指令,多个物理行需要用反斜杠连接成一个逻辑行

如:

#define LONG_MACRO_NAME \
this is a long macro definition \
that spans multiple lines

 将    LONG_MACRO_NAME   替换为   this is a long macro definition that spans multiple lines

 可以通过如下编译选项来指定来限定编译器只进行预处理操作:

gcc example.c -o example.i -E

 带参宏

//使用 pf 来替换 printf("%d",参数);
#define  pf(参数)  printf("%d",参数);// 求两个数据的较大值
#define max(a, b) a > b ? a : b// 求两个数据的较小值
#define min(a, b) a < b ? a : b

注意事项:

带参宏的特点:

直接文本替换,不做任何语法判断,更不做任何中间运算。

宏在编译的预处理阶段就被替换掉,运行中不存在宏。

宏将在所有出现它的地方展开,这一方面浪费了内存空间,另一方面有节约了切换时间。

 使用双井号粘贴字串

#define LAYER_INITCALL(num, layer)  __zinitcall_##layer##_##num

如果使用 LAYER_INITCALL(service, 1),那么预处理器会将其展开为 __zinitcall_service_1;如果使用 LAYER_INITCALL(feature, 2),则会展开为 __zinitcall_feature_2。

如果字串出现在最末尾,则最后的双井号必须去除,如果粘贴的字串并非出现在最末尾,则前后都必须加上双井号

另外,如果字串本身拼接为字符串,那么只需要使用一个井号即可

例如:

#define domainName(a, b) "www." #a "." #b ".com"
int main()
{printf("%s\n", domainName(baidu, aaa));
}//输出www.baidu.aaa.com

 

 条件编译

#define A 0
#define B 1
#define C 2#if Aprintf("真");
#endif// 二路分支
#if Aprintf("A");
#elif Bprintf("B");
#endif// 多路分支
#if Aprintf("A");
#elif Bprintf("B");
#elif Cprintf("C");
#endif

 ifndef和endif语句判断头文件中函数是否被重复定义

如对C的标准库进行定义时:

#ifndef stdio
#define stdiovoid printf。。。。。。scanf。。。。。。int。。。。。。float。。。#endif

有时候多个头文件中包含了相同的函数声明或定义,或者一个程序中重复引用了某些头文件,这样做是为了防止其被重复引用
 

参考:
c语言结构体一篇懂_1.结构体变量的第一个成员在与结构体变量偏移量为0的地址处。-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Matrix Equation(高斯线性异或消元+bitset优化)

题目&#xff1a; 登录—专业IT笔试面试备考平台_牛客网 思路&#xff1a; 我们发现对于矩阵C可以一列一列求。 mod2&#xff0c;当这一行相乘1的个数为奇数时&#xff0c;z(i,j)为1&#xff0c;偶数为0&#xff0c;是异或消元。 对于b[i&#xff0c;j]*c[i,j],b[i,j]可以…

【MQTT(4)】开发一个客户端,QT-Android安卓手机版本,Mosquitto替换成libhv库

我们采用 libhv是一个类似于libevent、libev、libuv的跨平台网络库&#xff0c;提供了更易用的接口和更丰富的协议。 https://github.com/ithewei/libhv?tabreadme-ov-file 编译脚本如下 Android compile WITH_MQTT #https://developer.android.com/ndk/downloads #export…

tof系统标定流程步骤详解

1、tof标定概述 系统校准是一个减少ToF系统中系统误差影响的过程,如图1.1所示。本文件旨在介绍校准方法、设备和软件 1.1 系统误差 1.1.1 周期误差 谐波失真导致的相位(距离)相关误差。 1.1.2 固定相位模式噪声 由于解调信号的时延取决于可见像素位置以及VCSEL和传感器…

c++中的最长递增子序列(Longest Increasing Subsequence)(算法章完结)

前言 hello大家好啊&#xff0c;我是文宇。 今天是最后一篇算法&#xff08;暂时性的&#xff0c;以后可能还有&#xff09; 最长递增子序列&#xff08;Longest Increasing Subsequence&#xff09; 最长递增子序列&#xff08;Longest Increasing Subsequence&#xff0c…

【Golang 面试基础题】每日 5 题(十)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

【机器学习】解开反向传播算法的奥秘

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 解开反向传播算法的奥秘反向传播算法的概述反向传播算法的数学推导1. 前向传播2…

Linux进程——程序地址空间详解

文章目录 程序地址空间地址空间与物理内存什么是程序地址空间管理程序地址空间虚拟地址与物理地址的映射页表的结构及其作用程序地址空间的作用 程序地址空间 我们之前学习内存的时候&#xff0c;有说内存的分布大概是这样的 其中堆由下而上&#xff0c;栈由上而下 除此之外&…

JavaScript青少年简明教程:函数及其相关知识(下)

JavaScript青少年简明教程&#xff1a;函数及其相关知识&#xff08;下&#xff09; 继续上一节介绍函数相关知识。 箭头函数&#xff08;Arrow Function&#xff09; 箭头函数是 ES6&#xff08;ECMAScript 2015&#xff09;及更高版本中引入的语法&#xff0c;用于简化函数…

LeetCode:删除排序链表中的重复元素(C语言)

1、问题概述&#xff1a;给定一个已排序链表的头&#xff0c;删除重复元素&#xff0c;返回已排序的链表 2、示例 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2] 示例 2&#xff1a; 输入&#xff1a;head [1,1,2,3,3] 输出&#xff1a;[1,2,3] 3…

深度解析Memcached:内存分配算法的优化之旅

&#x1f525; 深度解析Memcached&#xff1a;内存分配算法的优化之旅 Memcached是一个高性能的分布式内存缓存系统&#xff0c;广泛用于提高Web应用程序的性能。它通过减少数据库查询次数来加速数据检索。然而&#xff0c;Memcached的性能在很大程度上取决于其内存分配算法的…

前端三方库零碎(持续更新)

本文主要记录开发实践过程中遇到的前端库&#xff0c;做个记录总结&#xff0c;以备不时之需 easyui-datagrid EasyUI 是一个基于 jQuery 的用户界面插件库&#xff0c;提供了丰富的用户界面组件和工具&#xff0c;其中包括 datagrid&#xff08;数据表格&#xff09;组件。E…

2024年国际高校数学建模大赛(IMMCHE)问题A:金字塔石的运输成品文章分享(仅供学习)

2024 International Mathematics Molding Contest for Higher Education Problem A: Transportation of Pyramid Stones&#xff08;2024年国际高校数学建模大赛&#xff08;IMMCHE&#xff09;问题A&#xff1a;金字塔石的运输&#xff09; 古埃及金字塔石材运输优化模型研究…

spring(一)

一、spring特点 1.非侵入式&#xff1a;使用 Spring Framework 开发应用程序时&#xff0c;Spring 对应用程序本身的结构影响非常小。对领域模型可以做到零污染&#xff1b;对功能性组件也只需要使用几个简单的注解进行标记&#xff0c;完全不会破坏原有结构&#xff0c;反而能…

2024最新Selenium面试题(附带答案),建议收藏备用

一.你在TestNG中使用了哪些注解&#xff1f; TestBeforeSuiteAfterSuiteBeforeTestAfterTestBeforeClassAfterClassBeforeMethodAfterMethod 二.如何从Excel中读取数据&#xff1f; FileInputStream fs new FileInputStream(“excel文件路径”); Workbook wb WorkbookFact…

探索智慧校园资产入库功能,构建高效校园资产管理体系

在智慧校园的资产管理框架下&#xff0c;资产入库功能作为资产生命周期管理的开端&#xff0c;扮演着至关重要的角色。这一功能确保了新购置或转入的资产能够迅速而准确地被记录在系统中&#xff0c;从而无缝融入日常的管理流程。当资产入库时&#xff0c;系统要求详细登记一系…

2024最新前端学习路线指南!

2024最新前端学习路线指南&#xff01; 如果你正在寻找一份全面的前端学习路线图&#xff0c;那么这份精心打造的学习大纲恰好符合您的需求。无论您是新手还是经验丰富的开发者&#xff0c;这份路线图都能够帮助您系统地掌握前端开发的关键知识点&#xff0c;并在实践中不断提…

git连接远程仓库

一、本地新建代码,上传到远程仓库 1.git init #初始化本地仓库 2.git remote -v #查看当前仓库的远程地址 3.git remote add origin 远程仓库的URL 4.git branch master / git branch dev 创建 主分支或者 dev 分支 5.git checkout master/dev. 切换到主分支或者dev 分支…

Mysql-生产环境实战经验总结

文章目录 真实生产环境下的Mysql数据库机器配置如何规划互联网公司的生产环境数据库是如何进行性能压测1. 准备测试环境2. 构建测试场景3. 性能测试4. 监控与分析5. 资源压力测试6. 故障恢复测试7. 文档记录与复盘8. 安全与合规注意事项 如何为生产环境中的数据库部署监控系统1…

<PLC><HMI><汇川>在汇川HMI画面中,如何为UI设置全局样式?

前言 汇川的HMI软件是使用了Qt来编写的,因此在汇川的HMI程序编写过程,是支持使用qt的样式来自定义部件样式的,即qss格式。 概述 汇川的软件本身提供三个系统的style样式,我们可以直接使用,但是,如果系统提供的样式不符合你的需求,那么你可以对其进行修改,或者自己新建…

修改linux服务器上的mariadb/mysql数据库的密码

文章目录 一、查看数据库的状态二、修改密码 可能我们在最初安装数据库时没有设置密码或者已经设置了但是又想修改另一个密码&#xff0c;可以这样操作来修改我们的密码。 以数据库 mariadb 为例。 一、查看数据库的状态 使用命令 systemctl is-active mariadb 查看当前数据库…