【嵌入式C语言】指针数组结构体
指针与数组
- 指针与数组
- 指针数组
- 数组指针
- 多维数组
- 数组名的保存
- 结构体
- 定义结构体
- 定义结构体变量
- 使用typedef简化结构体声明
- 访问结构体成员
- 结构体内存分配
- 字节对齐
- 位域
- 定义位域
- 位域的限制
- 示例
指针与数组
指针数组和数组指针是两个不同的概念,它们涉及到指针和数组的组合使用。
指针数组
- 定义: 指针数组是一个数组,其中的每个元素都是一个指针。
- 示例:
int *ptrArray[5];声明了一个包含5个元素的指针数组,每个元素都是一个指向整数的指针。 - 用途: 指针数组常用于存储一组指针,每个指针可以指向不同类型的数据或不同位置的数组。
#include <stdio.h>
int main()
{char a[5] = {'a', 'b', 'c', 'd', 'e'};char *p[5];printf("sizeof(a) = %d\n", sizeof(a));printf("sizeof(p) = %d\n", sizeof(p));return 0;
}
输出
cd 'e:\CProject\output'
PS E:\CProject\output> & .\'指针数组.exe'
sizeof(a) = 5
sizeof(p) = 40
可以看到指针数组的大小是个数*对应类型的指针的大小
举例2
#include <stdio.h>
int main() {int a = 1, b = 2, c = 3;int *ptrArray[3] = {&a, &b, &c};// 打印指针数组中每个元素指向的值for (int i = 0; i < 3; i++) {printf("%d ", *ptrArray[i]);}return 0;
}
输出
PS E:\CProject\output> cd 'e:\CProject\output'
PS E:\CProject\output> & .\'指针数组.exe'
1 2 3
在这个例子中,ptrArray 是一个包含3个指针的数组,每个指针分别指向整数变量 a、b 和 c。
数组指针
- 定义: 数组指针是一个指针,它指向一个数组。
- 示例:
int (*ptr)[5];声明了一个指针,指向包含5个元素的整数数组。 - 用途: 数组指针常用于处理二维数组或作为指向动态分配数组的指针。
#include <stdio.h>
int main() {int arr[3][5] = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}};int (*ptr)[5] = arr;// 打印数组指针指向的数组中的元素for (int i = 0; i < 3; i++) {for (int j = 0; j < 5; j++) {printf("%d ", ptr[i][j]);}printf("\n");}return 0;
}
在这个例子中,ptr 是一个指针,指向包含5个元素的整数数组,它被初始化为指向二维数组 arr 的第一行。
总体而言,指针数组和数组指针提供了在数组和指针之间灵活切换的方式,依赖于实际需求选择使用哪一种形式。
多维数组
数组名的保存
- 定义一个指针,指向
int a[10];的首地址 - 定义一个指针,指向
int b[5][6];的首地址
#include <stdio.h>
int main()
{int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int b[3][4];int *p1 = a;int **p2 = b; // 这样是错误的,二维数组和二维指针没有关系return 0;
}
这样是错误的,二维数组和二维指针没有关系
二维数组是一行一行读取的,一次就读取4列的数据
二维指针是存储线性的地址
正确的读取方式
#include <stdio.h>
int main()
{int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int b[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};int *p1 = a;int(*p2)[4] = b; // 每次读4个printf("%d\n\n", *p1);printf("%d\n", *p2[0]);printf("%d\n", *p2[1]);printf("%d\n", *p2[2]);return 0;
}
举例2
int c[2][3][4];
int (*p)[3][4]; //T
结构体
C语言中的结构体(struct)是一种用户自定义的数据类型,它允许你将不同类型的数据组合在一起。这使得你可以创建更复杂的数据结构来表示现实世界中的实体。一个结构体可以包含多个成员(member),每个成员都有自己的数据类型和名称。
下面是一些关于C语言结构体的基本概念和用法:
定义结构体
要定义一个结构体,你需要使用struct关键字,后跟结构体的标签(可选),接着是花括号包围的一系列成员声明,最后以分号结束。
struct Point {int x;int y;
};
定义结构体变量
一旦定义了结构体,就可以声明该结构体类型的变量。有两种方式来做这件事:
- 在定义结构体的同时声明变量:
struct Point pt1, pt2;
- 先定义结构体,然后在其他地方声明变量:
struct Point;// ... 之后某个地方struct Point pt1, pt2;
如果你给结构体指定了标签(如上面例子中的Point),那么可以在后续代码中仅使用struct Point来声明新的变量。
使用typedef简化结构体声明
为了简化结构体变量的声明,通常会与typedef一起使用:
typedef struct {int x;int y;
} Point;
这样,以后可以直接使用Point作为类型名来声明结构体变量,而不需要再写struct Point。
访问结构体成员
结构体成员通过点运算符.来访问:
pt1.x = 10;
pt1.y = 20;
如果结构体是指针,则使用箭头运算符->来访问成员:
Point *p = &pt1;
p->x = 30; // 等价于 (*p).x = 30;
结构体内存分配
结构体变量的内存是在声明时分配的。如果你需要动态分配结构体的内存,可以使用malloc()或calloc()函数。
Point *p = (Point *)malloc(sizeof(Point));
if (p != NULL) {p->x = 40;p->y = 50;
}
// 使用完后记得释放内存
free(p);
字节对齐
#include <stdio.h>struct student
{char x; // 4 字节对齐int roll; // 4float marks; // 4
};
int main()
{struct student s1;printf("struct size: %d\n", sizeof(s1));return 0;
}
字节对齐:为了效率,希望牺牲一点空间换取时间的效率
分别看一下定义的顺序不同,占用的空间大小!
#include <stdio.h>struct student
{char x; // 2short y; // 2int roll; // 4
};struct stu
{char x; // 4int roll; // 4short y; // 4
};
int main()
{struct student s1;printf("struct size: %d\n", sizeof(s1));struct stu s2;printf("struct size: %d\n", sizeof(s2));return 0;
}

由于定义的顺序不同,占用的空间大小也不同!
第一种定义方式里,char剩余3bytes,可以给short类型的变量使用,如下图所示:
第二种定义的顺序,在内存中的分布如下
位域
位域(bit-fields)是C语言中的一种特殊结构体成员,它允许你定义一个特定宽度的字段,以位为单位。位域主要用于需要紧凑存储或与硬件通信的场合,比如嵌入式系统编程。
在位域中,你可以指定每个成员占用的位数,这可以减少内存的使用量。然而,使用位域也可能会导致代码的可移植性问题,因为不同的编译器可能对位域的实现有所不同,包括它们如何打包和对齐数据。
定义位域
位域通过在结构体成员声明后添加冒号和位宽来定义。以下是位域的一个简单例子:
struct packed_struct {unsigned int f1 : 1; // 1 bitunsigned int f2 : 3; // 3 bitsunsigned int f3 : 4; // 4 bits
};
在这个例子中,packed_struct包含三个位域成员:f1、f2 和 f3,分别占据1位、3位和4位。请注意,位域成员必须是整数类型(如int、unsigned int等),并且不能是数组或指针。
位域的限制
- 位域的大小:位域的最大宽度取决于底层整型的大小。例如,在大多数系统上,
unsigned int通常是32位,所以你不能创建超过32位的位域。 - 匿名位域:有时会看到不带名称但带有宽度的位域,这样的位域用于填充或者对齐。例如,
unsigned int : 2;将占用2位,但没有关联的变量名。 - 不可寻址性:由于位域是由多个位组成的,因此不能取位域成员的地址。
- 端序依赖:不同体系结构上的字节顺序(大端或小端)会影响位域的实际布局。
示例
这里有一个更完整的示例,展示了如何使用位域:
#include <stdio.h>struct Flags {unsigned int flag1 : 1;unsigned int flag2 : 1;unsigned int : 6; // 匿名位域,用于填充或对齐unsigned int flag3 : 1;
};int main() {struct Flags flags;flags.flag1 = 1;flags.flag2 = 0;flags.flag3 = 1;printf("flag1: %d\n", flags.flag1);printf("flag2: %d\n", flags.flag2);printf("flag3: %d\n", flags.flag3);return 0;
}
这个程序定义了一个Flags结构体,其中包含了三个标志位,每个都只占用了1位。注意,我们还插入了一个6位的匿名位域,用于确保后续的位域从一个新的字节开始(假设编译器按照8位边界对齐)。
请记住,尽管位域提供了一种节省空间的方法,但在编写代码时应该考虑到它的可移植性和潜在的复杂性。如果你不需要精确控制位级别的数据,通常最好使用普通的结构体成员。
【嵌入式C语言】 https://www.bilibili.com/video/BV1RW411G7cr/?p=44&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933
相关文章:
【嵌入式C语言】指针数组结构体
指针与数组 指针与数组指针数组数组指针 多维数组数组名的保存 结构体定义结构体定义结构体变量使用typedef简化结构体声明访问结构体成员结构体内存分配字节对齐位域定义位域位域的限制示例 指针与数组 指针数组和数组指针是两个不同的概念,它们涉及到指针和数组的…...
国产数据库TiDB从入门到放弃教程
国家层面战略,安全的角度,硬件、软件国产化是趋势,鸿蒙电脑操作系统、鸿蒙手机操作系统…数据库也会慢慢国产化,国产数据库TiDB用起来比OceanBase丝滑,本身没有那么重。 从入门到放弃 1. 介绍1.1 TiDB 的主要特点1.2 T…...
深入解析 Spring 属性:spring.codec.max-in-memory-size
在现代 Web 应用开发中,数据传输的大小和效率直接影响到系统的性能和稳定性。Spring WebFlux 作为一种响应式编程框架,提供了强大的数据流处理能力。在使用 WebFlux 时,spring.codec.max-in-memory-size 是一个关键配置,用于定义应…...
在K8S中,如何查看Pod状态的详情?事件显示cpu不足如何处理?
在Kubernetes中,查看Pod状态的详细通常设计使用kubectl命令行工具,这是kubernetes提供的一个强大的管理工具。以下是如何查看Pod状态详情的步骤: 1. 查看Pod状态详情 列出所有Pod: 使用kubectl get pods命令可以查看集群所有Po…...
ArcGIS教程(009):ArcGIS制作校园3D展示图
文章目录 数据下载校园3D展示图制作创建要素类矢量化【楼】要素矢量化【绿地】矢量化【范围】矢量化处理打开ArcScene添加动画数据下载 https://download.csdn.net/download/WwLK123/90189025校园3D展示图制作 创建要素类 添加底图: 新建【文件地理数据库】,并修改名称为【…...
REDIS2.0
string list hash set 无序集合 声明一个key,键里面的值是元素,元素的类型是string 元素的值是唯一的,不能重复 多个集合类型之间可以进行并集,交集,集查的运算 sadd test1 a b c c d :添加5个元素&am…...
算法练习——模拟题
前言:模拟题的特点在于没有什么固定的技巧,完全考验自己的代码能力,因此有助于提升自己的代码水平。如果说一定有什么技巧的话,那就是有的模拟题能够通过找规律来简化算法。 一:替换所有问号 题目要求: 解…...
京东供应链创新与实践:应用数据驱动的库存选品和调拨算法提升履约效率
2024 年度总结系列 2024 年 10 月,京东零售供应链技术团队凭借其在库存选品与调拨技术上的创新与实践,荣获运筹与管理学领域的国际顶级奖项 Daniel H. Wagner Prize。本文为您介绍获奖背后的供应链技术创新和落地应用。 00 摘要 在电商行业中&#x…...
pytorch张量的fill_方法介绍
在 PyTorch 中,fill_ 是一个张量的原地操作方法,用于将张量中的所有元素填充为指定的值。 方法签名 Tensor.fill_(value)参数 value (float or int): 要填充到张量中的值。 返回值 返回调用该方法的张量本身,且是经过修改后的张量。 特…...
WAP短信格式解析及在Linux下用C语言实现
WAP短信格式解析及在Linux下用C语言实现 一、引言二、WAP短信格式概述三、WAP短信头的内容四、UDHI与WAP短信体的关系五、在Linux下用C语言解析WAP短信头及短信体内容一、引言 在移动通信领域,短信作为一种古老却稳定的通信方式,一直扮演着重要的角色。随着技术的发展,短信…...
Linux的诞生与发展、体系结构与发行版本
Linux作为一个开源操作系统,在过去几十年中一直扮演着至关重要的角色。它不仅深刻影响了服务器、桌面和移动设备,还成为了开源运动的重要组成部分。本文将介绍Linux的历史、体系结构、以及主要的发行版,帮助你更好地了解Linux的方方面面。 一…...
为什么Mysql用B+树作为索引
首先,能作为索引的数据结构有很多,例如数组、链表、二叉树 数据和索引都是存储在磁盘里的。 我们通过索引来查询数据时,先从磁盘读取索引到内存,再通过索引从磁盘中找到某行数据,然后读入到内存。 要设计一个适合 MySQ…...
探索 DC-SDK:强大的 3D 地图开发框架
在现代 Web 开发中,地理信息系统(GIS)和 3D 地图可视化变得越来越重要。dc-sdk 是一个基于 Cesium 的开源 WebGL 地图开发框架,它提供了丰富的地图可视化功能和简单易用的 API,使开发者能够轻松地在 Web 应用中集成 3D…...
C#高级篇 反射和属性详解【代码之美系列】
🎀🎀🎀代码之美系列目录🎀🎀🎀 一、C# 命名规则规范 二、C# 代码约定规范 三、C# 参数类型约束 四、浅析 B/S 应用程序体系结构原则 五、浅析 C# Async 和 Await 六、浅析 ASP.NET Core SignalR 双工通信 …...
算法 class 005 (对数器C语言实现)
对数器的概念: 用来测试你的算法是否正确。 怎么做呢? 1:比如,写个冒泡排序,作为对比的对象 2:生成一个随机数 数组,用来测试 3:用冒泡排序和你想要验证的那个排序算法,同…...
windows系统安装完Anaconda之后怎么激活自己的虚拟环境并打开jupyter
1.在win主菜单中找到Anaconda安装文件夹并打开终端 文件夹内有所有安装后的Anaconda的应用软件和终端窗口启动窗口 点击Anaconda Prompt(Anaconda)就会打开类似cmd的命令终端窗口,默认打开的路径是用户名下的路径 2.激活虚拟环境 使用命令…...
leetcode 面试经典 150 题:矩阵置零
链接矩阵置零题序号73题型二维数组解题方法标记数组法难度中等熟练度✅✅✅✅ 题目 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1: 输入:matrix [[1,1,1],[1,0,1]…...
SQL中的TRIM用法
TRIM 是 SQL 中用于去除字符串两端(左侧和右侧)的空格或特定字符的函数。这个函数常用于清理数据中的无效空白字符,尤其是在从外部系统导入数据时,常常会遇到数据两端有不必要的空格,使用 TRIM 可以去除这些多余的字符…...
Git Flow 工作流:保障修改不破坏主功能的完整指南20241230
Git Flow 工作流:保障修改不破坏主功能的完整指南 引言 在团队协作和个人项目中,Git Flow 是一种可靠的分支管理策略。通过清晰的分工和规范的流程,它能有效保障代码改动的安全性,避免修改破坏主功能,同时提高开发效…...
CentOS 7安装Docker详细教程
本文以 CentOS7.8 为例安装 Docker 26.1.4 、Docker Compose、以及 Docker 镜像仓库。 1.安装Docker社区版 1.1 安装准备 1.1.1 检查系统环境 Docker 不支持32位的 CentOS 7 系统,要求系统内核版本为3.10 以上,可以通过命令 uname -r 来查看当前系统…...
ThinkPHP实现定时任务的操作步骤
到一个需求:定时检查设备信息,2分钟没有心跳的机器,推送消息给相关人员,用thinkphp5框架,利用框架自带的任务功能与crontab配合来完成定时任务。第一步:分析需求先写获取设备信息,2分钟之内没有…...
避坑指南:Ecology9流程创建失败的7个常见错误及解决方案(附调试技巧)
Ecology9流程创建失败的7个典型陷阱与深度解决方案 1. 权限配置:被忽视的系统级限制 权限问题往往是流程创建失败的首要原因。许多实施顾问只关注表面错误提示,却忽略了系统底层的权限体系设计。Ecology9的权限控制分为三个层级: 组织架构权限…...
Amundsen多租户架构:企业级数据隔离的终极解决方案
Amundsen多租户架构:企业级数据隔离的终极解决方案 【免费下载链接】amundsen Amundsen is a metadata driven application for improving the productivity of data analysts, data scientists and engineers when interacting with data. 项目地址: https://git…...
《YOLOv11 实战:从入门到深度优化》002、环境搭建:从零配置YOLOv11开发与训练环境
002、环境搭建:从零配置YOLOv11开发与训练环境 昨天深夜调试一个边缘设备上的推理异常,问题最终定位到CUDA版本和torch不匹配——这种环境配置埋下的坑,往往比算法本身更难排查。今天咱们就老老实实把YOLOv11的环境从头搭一遍,这份…...
谷歌开源Gemma 4:256K原生多模态,免费商用
谷歌刚刚发布了新一代开源大模型Gemma 4,直接把Gemini 3的核心技术下放了。2026年4月2日,谷歌如约献上复活节惊喜:Gemma 4 正式开源。从手机到服务器全覆盖四种规格,首次加入MoE架构,原生支持文本图像音频三模态&#…...
别再自己写Word转PDF了!用kkFileView 4.0.0开源项目快速搭建一个微服务接口
微服务架构下文档转换的最佳实践:kkFileView 4.0深度整合指南 在当今企业级应用开发中,文档格式转换是一个看似简单却暗藏玄机的技术需求。想象一下这样的场景:你的合同管理系统需要将动态生成的Word文档转换为PDF格式发送给客户,…...
高级编程 第一节:Python中的时间处理
一、时间标准库:time 1、time库介绍 time库是Python中处理时间的标准库,提供获取系统时间并格式化输出功能,但是功能上,没有datatime库强大。 time库中相关概念: 时间戳:格林威治时间1970年01月01日00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数,…...
提升数据采集效率:用快马AI生成支持异步与代理的新闻监控爬虫
最近在做一个新闻监控项目,需要实时跟踪多个新闻网站的头条更新。传统爬虫开发中,反爬机制、数据清洗这些重复性工作特别耗时,经过一番摸索,我发现用InsCode(快马)平台可以快速生成结构优化的爬虫代码,效率提升非常明显…...
终极指南:如何快速配置Cubism.js连接Ganglia数据源实现系统监控可视化
终极指南:如何快速配置Cubism.js连接Ganglia数据源实现系统监控可视化 【免费下载链接】cubism Cubism.js: A JavaScript library for time series visualization. 项目地址: https://gitcode.com/gh_mirrors/cu/cubism Cubism.js是一款强大的JavaScript时间…...
Helloagents-13travel agent学习笔记
承接上文Helloagents-13.智能旅行助手学习笔记 _helloagents旅游项目-CSDN博客 1.全链路架构梳理 1. 订单接入(用户输入 -> 后端接收) 前端 (Vue): 用户在网页上填好目的地(如“悉尼”)、天数、出发日期等&#x…...

