C语言结构体和位段

news2024/11/22 6:23:18

自定义类型:结构体及联合和枚举

  • 一.结构体类型的声明
    • 1.1 结构体的概念
    • 1.2结构的声明
    • 1.3特殊的声明
    • 1.4结构体的自引用
    • 1.5可以使用typedef重命名
  • 二.结构体变量的创建和初始化
    • 2.1结构体变量的初始化使用`{}`
    • 2.2初始化:定义变量的同时赋初值。
    • 2.3结构体嵌套及初始化
  • 三.结构体成员访问操作符
  • 四.结构体内存对齐
    • 4.1对齐规则
      • 练习1
      • 练习2
      • 练习3
      • 练习4(嵌套结构体的对齐数)
    • 4.2修改默认对齐数
  • 五.结构体传参
  • 六.联合体
    • 6.1联合体类型的声明
    • 6.2联合体的特点
    • 6.2计算联合体的大小
    • 6.3用联合体判断大小端字节序
  • 七.枚举类型
    • 7.1枚举类型的声明
    • 7.2枚举的优点
    • 7.3 枚举类型的使用

一.结构体类型的声明

1.1 结构体的概念

结构是一些值的集合,这些称为成员变量,结构的每个成员可以是不同类型的变量

1.2结构的声明

struct tag
{
 member-list;
}variable-list;

假如是一个大学生,可以用以下带代码描述

struct Stu
{
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
 }; 

这里注意结构体后面的分号是不可以丢的

1.3特殊的声明

在声明结构体的时候可以使用匿名结构体
但是匿名结构体只可以使用一次

//匿名结构体类型
struct
{
 int a;
 char b;
 float c;
}x;
struct
{
 int a;
 char b;
 float c;
}a[20], *p;

编译器会把上面的两个声明当成完全不同的两个类型,所以是非法的。
匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使⽤⼀次。

1.4结构体的自引用

在结构中包含⼀个类型为该结构本⾝的成员是可以的
比如:定义一个链表结点

struct Node
{
	int data;
	struct Node* next;
};

1.5可以使用typedef重命名

typedef struct Node
{
 int data;
 struct Node* next;
}Node;

二.结构体变量的创建和初始化

2.1结构体变量的初始化使用{}

struct Point
{
 int x;
 int y;
}s1; //声明类型的同时定义变量s1
struct Point s2; //定义结构体变量s2

2.2初始化:定义变量的同时赋初值。

struct Point p3 = {x, y};

2.3结构体嵌套及初始化

struct Node
{
 int data;
 struct Point p;
 struct Node* next;
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};

struct Stu
{
 char name[15];
 int age;
};
struct Stu s = {.age=20, .name="zhangsan"};//初始化

三.结构体成员访问操作符

结构成员访问操作符有两个⼀个是 . ,⼀个是 -> .

有以下两种方式:
结构体变量.成员变量名
结构体指针—>成员变量名

struct student
{
	char name[10];
	int age;
};

int main()
{
	struct student stu = { "zhangsan",10 };
	struct student* pstu = &stu;
	printf("%d", (*(pstu)).age);
	printf("%d",pstu->age);
	return 0;
}

四.结构体内存对齐

4.1对齐规则

1. 结构体的第一个成员相对于结构体变量起始位置偏移量为0的地址处
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍地址
3. 结构体总大小为 最大对其数(结构体中每个成员变量都有一个对齐数,所有对齐数中最大的)的整数倍
4. 如果要是嵌套了结构体的情况,嵌套的结构体成员对齐到自己成员中的最大对其数的整数倍,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍

以下有几个练习:

练习1

计算下列结构体大小:

struct S1
{
 char c1;
  char c2;
 int i;
};
printf("%d\n", sizeof(struct S1));

结果是在这里插入图片描述

下面画图来解释以下原因:
在这里插入图片描述

练习2

计算下列结构体大小:

struct S2
{
	char c1;
	int i;
	char c2;
};
int main()
{
	printf("%d\n", sizeof(struct S2));
	return 0;
}

结果是在这里插入图片描述

下面画图来解释以下原因
在这里插入图片描述
因为对齐数要是最大对齐数的整数倍,所以就是12

练习3

struct S3
{
	double d;
	char c;
	int i;
};
int main()
{
	printf("%d\n", sizeof(struct S3));
	return 0;
}

运行结果是在这里插入图片描述

下面画图来解释以下原因:
在这里插入图片描述

练习4(嵌套结构体的对齐数)

struct S3
{
	double d;
	char c;
	int i;
};

struct S4
{
	char c1;
	struct S3 s3;
	double d;
};
int main()
{

	printf("%d\n", sizeof(struct S4));
	return 0;
}

运行结果在这里插入图片描述

下面画图来解释以下原因:
在这里插入图片描述

4.2修改默认对齐数

可以使用#pragam pack(1),设置默认对齐数为1
pragam pack()取消设置默认对齐数

五.结构体传参

struct S
{
	 int data[1000];
	 int num;
};
struct S s = {{1,2,3,4}, 1000};
//结构体传参
void print1(struct S s)
{
	printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
 	printf("%d\n", ps->num);
}
int main()
{
	 print1(s); //传结构体
	 print2(&s); //传地址
 	return 0;
}

六.联合体

6.1联合体类型的声明

联合体的特点是所有成员共用同一块内存空间。所以联合体也叫:共用体
给联合体其中⼀个成员赋值,其他成员的值也跟着变化。

//联合类型的声明
union Un
{
 char c;
 int i;
};
int main()
{
 //联合变量的定义
 union Un un = {0};
 //计算连个变量的⼤⼩
 printf("%d\n", sizeof(un));
 return 0;
}

运行结果:

4

6.2联合体的特点

联合的成员是共用同⼀块内存空间的,这样⼀个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。

代码

#include <stdio.h>
//联合类型的声明
union Un
{
 char c;
 int i;
};
int main()
{
 //联合变量的定义
 union Un un = {0};

 printf("%p\n", &(un.i));
 printf("%p\n", &(un.c));
 printf("%p\n", &un);
 return 0;
}

输出结果:

001AF85C
001AF85C
001AF85C

6.2计算联合体的大小

联合的大小至少是最⼤成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

代码:

union Un1
{
 char c[5];
 int i;
};
union Un2
{
 short c[7];
 int i;
};
int main()
{
 //下⾯输出的结果是什么?
 printf("%d\n", sizeof(union Un1));
 printf("%d\n", sizeof(union Un2));
 return 0;
}

运行结果:
在这里插入图片描述

下面画图来解释以下原因:
在这里插入图片描述

因为Un1的char c[5]需要占用5个字节,5不是4的倍数,所以就是8个字节
Un2的char c[7]要占用14个字节,但是14不是结构第默认对齐数的最小公倍数,所以就是16

6.3用联合体判断大小端字节序

int check_sys()
{
 union
 {
 int i;
 char c;
 }un;
 un.i = 1;
 return un.c;
}

七.枚举类型

7.1枚举类型的声明

enum Day//星期
{
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};
enum Sex//性别
{
 MALE,
 FEMALE,
 SECRET
}enum Color//颜⾊
{
 RED,
 GREEN,
 BLUE
};

1. 以上定义的 enum Day , enum Sex ,enum Color 都是枚举类型。
2. {}中的内容是枚举类型的可能取值,也叫 枚举常量 。
3. 这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。

enum Color//颜⾊
{
 RED=2,
 GREEN=4,
 BLUE=8
};

7.2枚举的优点

  1. 增加代码的可读性和可维护性
  2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
  3. 便于调试,预处理阶段会删除 #define 定义的符号
  4. 使用方便,一次可以定义多个常量
  5. 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用

7.3 枚举类型的使用

enum Color//颜⾊
{
 RED=1,
 GREEN=2,
 BLUE=4
};
enum Color clr = GREEN;

在C语言中是可以的,但是在C++是不行的,C++的类型(语法)检查比较严格。

文章到这里结束了!!!如果有错,请立刻指正,谢谢!!!

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

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

相关文章

基于FFmpeg,实现播放器功能

一、客户端选择音视频文件 MainActivity package com.anniljing.ffmpegnative;import android.Manifest; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Ur…

【python笔记】requests模块基础总结

前言 菜某笔记总结&#xff0c;如有错误请指正。&#xff08;抱歉可能我用渗透的靶场做的功能演示&#xff0c;让单纯想看爬虫整理的朋友不好理解&#xff0c;主要看一下requests库的写法吧&#xff0c;关于sql靶场&#xff0c;文件上传靶场什么的都当做网站的名字吧&#xff…

无法打开源文件“opencv2/opencv.hpp“

如图报错&#xff0c;看见就非常高血压 解决方案&#xff1a; 1.打开项目属性 第二步&#xff0c;注意你如果跑的是Debug&#xff0c;那么你在项目属性里面设置的必须选择Debug模式&#xff0c;跑的Release模式&#xff0c;则你必须要设置相应的Release模式&#xff01;否则你…

【金华模式】双龙旅游引燃露营设计和文旅产融合新方式

&#xff08;中国国际教育电视台 黎明&#xff09;金华双龙风景旅游区位于浙江省金华市北郊的金华山麓&#xff0c;是一处融自然山水、溶洞群景观、科普探险、康体休闲、避暑度假、观光朝圣于一体的景区。旅游区人文积淀深厚&#xff0c;道、儒、释文化兼收并蓄&#xff0c;东汉…

Android Studio的代码笔记--Adapter+GridView学习

AdapterGridView学习 AdapterGridViewSimpleAdapterGridViewactivity_main.xmlappicon.xmlMainActivity 自定义BaseAdapterGridView已下载应用PackageInfoAppAdapterMainActivity2 其他获取已下载应用信息函数获取所有应用信息函数ImageView产生圆角的方法背景设置很渐变设置选…

二、远程控制树莓派(在用一个Wifi下)

VNC是一个图形桌面共享系统&#xff0c;利用一台计算机或移动设备&#xff08;运行VNC查看器&#xff09;远程控制另一台计算机&#xff08;运行VNC服务器&#xff09;的桌面。 Step1&#xff1a;树莓派&#xff1a;安装VNC服务器&#xff08;树莓派自带&#xff09; 打开方式…

从 Android 手机恢复删除的数据的10个有效工具

您是否曾经在 Android 手机上遇到过数据丢失的情况&#xff0c;即您拍摄的瞬间或其他数据意外丢失&#xff1f; 就我而言&#xff0c;我多次遇到过此类数据丢失的情况&#xff0c;相信我&#xff0c;没有什么比从手机中丢失所有重要数据更严重的了。这就像一场噩梦&#xff0c…

102基于matlab的PCA+ELM和PCA+PSO-ELM的费用估计

基于matlab的PCAELM和PCAPSO-ELM的费用估计&#xff0c;输出输出两者的预测误差并进行比较&#xff0c;输出优化后的迭代曲线。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 102matlab PCAPSOELM (xiaohongshu.com)

数据标注公司如何确保数据安全?景联文科技多维度提供保障

数据标注公司通常拥有大量的AI数据和用户数据&#xff0c;保护数据安全是数据标注公司的重要任务。 数据标注公司确保标注数据的安全可以从制度、人员、工具等多个方面入手&#xff0c;建立完善的安全管理体系和审计机制&#xff0c;加强应急预案和备份机制的建立&#xff0c;以…

Docker容器:docker推送镜像至Harbor

目录 1、Harbor创建项目 2、进入test项目&#xff0c;查看推送命令 3、在docker服务器上准备一个镜像 4、修改docker客户端配置 5、重启docker服务 6、docker登录Harbor 7、docker镜像推送到Harbor 1、Harbor创建项目 2、进入test项目&#xff0c;查看推送命令 3、在dock…

路由器静态路由的配置

路由器静态路由的配置步骤如下&#xff1a; 进入系统视图。输入命令sys进入系统视图。配置路由器的接口IP地址。命令格式为int g0/0/0&#xff0c;其中g0/0/0表示路由器的接口&#xff0c;可以根据实际情况进行修改。然后使用命令ip add配置接口的IP地址。配置下一跳地址。在静…

Node.js黑马时钟案例

先上没有使用node.js之前的html部分代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title></title><style>* {margin: 0;padding: 0;}html,body {height: 100%;overflow: hidden;backgrou…

Appium 自动化测试 —— Appium的环境搭建与设置流程!

1、Appium 环境搭建&#xff1a; 学习 appium 最大的难处之一在于环境的安装&#xff0c;安装流程比较繁琐&#xff0c;安装的工具和步骤也较多&#xff0c;以下是基于 Windows 系统下的 Android 手机端的安装流程。就像我们在用 Selenium 进行 web 自动化测试的时候一样&…

RocketMQ源码 Broker-SubscriptionGroupManager 订阅组管理组件源码分析

前言 SubscriptionGroupManager 继承了ConfigManager配置管理组件&#xff0c;拥有将内存数据持久化到磁盘文件subscriptionGroup.json的能力。它主要负责维护所有消费组在内存中的订阅数据。 源码版本&#xff1a;4.9.3 源码架构图 核心数据结构 主要的数据结构比较简单&am…

Java - 异常(三)- 声明异常(throws)和手动抛出异常throw

目录 6.3 方式2&#xff1a;声明异常&#xff08;throws&#xff09; 6.4 手动抛出异常throw 6.4.1 概述 6.4.2 使用格式&#xff1a; 6.4.3 实例代码 6.4.4 为什么要手动抛出异常对象&#xff1f; 6.4.5 如何理解“自动”和“手动” 抛出异常对象 6.4.6 注意点 ❓面试…

@Scheduled任务调度/定时任务-非分布式

1、功能概述 任务调度就是在规定的时间内执行的任务或者按照固定的频率执行的任务。是非常常见的功能之一。常见的有JDK原生的Timer, ScheduledThreadPoolExecutor以及springboot提供的Schduled。分布式调度框架如QuartZ、Elasticjob、XXL-JOB、SchedulerX、PowerJob等。 本文…

GPT4All 本地部署教程

省流&#xff1a;偷懒的可以直接看第二章的GPT4All部署 一. GPT4All README 根据官方网站GPT4All的描述&#xff0c;它是一个开源大型语言模型&#xff0c;可在CPU和几乎任何GPU上本地运行 github source: https://github.com/nomic-ai/gpt4all GPT4All Website and Models…

目标检测检测精度

在一个数据集检测中&#xff0c;会产生四类检测结果&#xff1a;TP、TN 、FP 、FN&#xff1a; T ——true 表示正确 F——false 表示错误 P—— positive 表示积极的&#xff0c;看成正例 N——negative 表示消极的&#xff0c;看成负例 我的理解&#xff1a;后面为预测结…

Postman-脚本自动化及定时执行脚本(7)

一.postman脚本自动化&#xff08;从postman至Newman可以一键执行脚本并生成报告&#xff1a;&#xff09; Postman Newman 是一个 CLI&#xff08;命令行界面&#xff09;工具&#xff0c;可以使用它来运行 Postman 中的集合&#xff08;Collection&#xff09;和环境&#xf…

懒惰的数独——lodash的shuffle方法实现随机打乱的效果

1.效果 2.代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title></title><script src"https://cdn.jsdelivr.net/npm/vue2.5.17/dist/vue.js"></script><script src&q…