朝花夕拾 · C语言 | 结构体篇

告别第三方应用!用Android原生API搭建Miracast投屏接收器 本文深入探讨如何利用Android原生API开发Miracast接收器,绕过第三方依赖,实现高效的屏幕共享。通过Wi-Fi P2P直连、反射调用隐藏API和RTSP会话协商等核心技术,为开发者提供了一套完整的Miracast接收端解决方案,适用于多屏协同场景。 阅读详情

一.结构体的声明

struct 名称
{
        数据类型成员1;
        数据类型成员2;
        数据类型成员3;
}

struct date 
{
        int year,
        int mon,
        int day,
};
struct time

{
        int hour,
        int min,
        int sec,

};

struct datetime 
{
        struct date 
        {
                int year;
                int mon;
                int day;
        };
        struct time 
        {
                int hour;
                int min;
                int sec;
        };

};

注意:
1.声明结构体的时候,结构体后面的“;“不能省。
2.结构体成员之间用" ; "隔开。
3.struct 后面的“名称可以省略,省略后就是一个匿名结构体。

二.结构体变量定义

int  num;
结构体类型 变量名;

struct date mydate;
struct
{
        int year;
        int mon;
        int day;
}mydate;    //匿名结构体,由于没有定义变量名,所以为一次性

声明结构体类型的同时,定义了一个变量,变量的变量名mydate:

三.结构体初始化


全部初始化:

struct date mydate = { 2026,8,6};
struct datetime 
{
        struct date mdate 
        struct time mtm;

};
struct datetime mydt = {{2026, 8, 6}, {14, 5, 23}};

部分初始化:

struct date mydate =
{
. year=2024,
. day = 6,
};

四.结构体数据成员的访问

  • 通过结构体变量访问结构体成员

结构变量变量名.成员1;
结构变量变量名.成员2;
结构变量变量名.成员3;
mydate.year:
mydate.mon;
mydate.day:

  • 通过结构体指针访问结构体成员

结构体指针->成员1;
结构体指针->成员2;
结构体指针->成员3;
结构变量变量名.成员1;表达式的结果取决成员的数据类型。

五.结构体的存储方式

原则:

1.结构体成员在内存中存储时,成员必须存储在自己字节大小的整数倍中;

2.结构体整体占的内存大小,是结构体中最大成员字节整数倍

注意:

1.在不同位系统下,相同结构体在内存中占的内存空间可能不一样

原因:64位系统long/指针类型占8字节;32位系统long/指针类型占4字节。

2.可以强制让结构体内存按指定字节数对齐

#pragma pack(1)    //强制结构体按1字节对齐
struct stu{
int a;
char b;
int c;
};
#pragma pack()    //取消结构体按1字节对齐

数组的对齐值等于其元素类型的对齐值,不等于整个数组的字节数。

六.结构体做为函数参数传递

  • 如果要在被调函数中修改主调函数中的结构体变量,则传递结构体变量的地址;
  • 如果在被调函数中使用主调函数中定义的结构体变量,可以值传递,也可以传地址。

七.结构体数组

struct  名称 数组名[元素个数];
struct  名称 数组名[元素个数]={{ },{ },{ }};

数组名 [下标];---》数据类型:“struct 名称” 类型

void print_stu_info(stu *p,int len)
{
    for(int i=0;i<len;i++)
	{    
            printf("%s %d %d\n",p[i].name,p[i].age,p[i].score);
            printf("%s %d %d\n",(p+i)->name,(p+i)->age,(p+i)->score);
            printf("%s %d %d\n",(*(p+i)).name,(*(p+i)).age,(*(p+i)).score);
    }
}

八.共用体/联合体

1.基本语法

声明共用体:

union  名称

{

        数据类型  成员1;

        数据类型  成员2;

        数据类型  成员3;        

};

定义共用体变量:

union  名称  变量名;

在使用共用体类型数据时要注意以下一些特点:

(1)同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一种,而不是同时存放几种。也就是说,每一瞬时只有一个成员起作用,其他的成员不起作用,即不是同时都存在和起作用。
(2)共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员就失去作用。例如有以下赋值语句:

union
{int i;
char ch;
float f;
}a,b,c;

a.i=l;
a.c='a';
a.f=1.5;

在完成以上3个赋值运算以后,只有a.f是有效的,a.i和a.c已经无意义了。此用"printf("%d",a.i);"是不行的,而用“printf("%f",a.f);"是可以的,因为最后一次的赋值是向a.f赋值。因此在引用共用体变量时应十分注意当前存放在共用体变量中的究竟是哪个成员。
(3)共用体变量的地址和它的各成员的地址都是同一地址。例如,&a、&a.i、&a.c、&a.f都是同一地址值,其原因是显然的。
(4)不能对共用体变量名赋值,也不能企图引用变量名来得到一个值,又不能在定义共用体变量时对它初始化。例如,下面这些都是不对的:

union
{int i;
char ch;
float f;
}a=(1,'a',1.5); //不能初始化
a=l;            //不能对共用体变量赋值
m=a;            //不能引用共用体变量名以得到一个值

(5)不能把共用体变量作为函数参数,也不能使函数带回共用体变量,但可以使用指向共用体变量的指针(与结构体变量这种用法相仿)。

(6)共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型定义中,数组也可以作为共用体的成员。

2.内存大小端存储方式

小端:内存的高地址存储高字节位,内存的低地址存储低字节位;

大端:内存的高地址存储低字节位,内存的低地址存储高字节位;

//指针判断
int a=0x11223344;
char *p=(char*)&a;
printf("%d\n",*p);    //输出0x44,说明为小端

//共用体判断
union s
{
	int a;
	char b;
}p;

int main()
{
	p.a=1;
	printf("%d\n",p.b);    //输出1,说明为小端
}

九.枚举类型

  • 1.基本语法

枚举类型的声明:

enum 名称

{

        枚举常量1;//默认从0开始,枚举常量本质为int型数据

        枚举常量2;

        枚举常量3;

};

        

1.枚举里面的成员都是枚举常量,都是整型常量,所以不需要写数据类型。

2.枚举常量根据行业规范,一般写成大写方式,和普通变量区分;
3.枚举中的枚举常量,类似于整形符号常量,可以直接被引用;
4.枚举中的常量和常量之间用逗号隔开;
5.枚举中的枚举常量如果没有给定初始值,则默认从0开始;
如果给其中的某个枚举常量给定了初始值,则后面的常量以该值为基础自增1;

  • 2.枚举变量

enum 名称变量名;
枚举变量是枚举类型,但本质是一个整形,可以作为参数直接使用。
变量名=枚举常量;

// 定义一个名为 LogLevel 的枚举类型
typedef enum {
    LOG_ERROR = 1,    // 可以显式赋值,对应你作业里的 1
    LOG_WARNING = 2,
    LOG_INFO = 3
} LogLevel;
// 函数定义:接收一个 LogLevel 类型的参数
void write_log(LogLevel level, const char *message) {
    // 在函数内部,你可以直接拿 level 做判断
    if (level == LOG_ERROR) {
        // 处理错误...
    }
    // 或者用 switch 语句,这也是最推荐的方式
    switch (level) {
        case LOG_ERROR:
            printf("[ERROR] ");
            break;
        case LOG_WARNING:
            printf("[WARNING] ");
            break;
        case LOG_INFO:
            printf("[INFO] ");
            break;
        default:
            printf("[UNKNOWN] "); // 防御性编程,防止传入无效数字
            break;
    }
    printf("%s\n", message);
}

枚举类型作为参数,在C语言中本质上是按整数传递。它的用法非常直接,和传递 int 几乎一样。

在正式项目中,凡是涉及到“有限个固定选项”的参数(日志等级、传输协议类型、游戏难度等),都应该优先使用枚举来代替 #define 或 int。它不仅让函数签名更清晰,还能让你在调试时节省大量时间。

十.typedef

typedef struct stu{
char name[32];
int age;
int score;
}STU_S    //大写+_S表示struct
typedef unsigned int u32:
typedef unsigned char u8;
typedef unsigned short u16 ;
typedef unsigned long u64 ;
typedef signed int s32 ;
typedef struct
{
    int data;
    Node *pnext;  // ❌ typedef 的别名 Node 是在整个结构体定义结束之后才生效的。也就是说,当编译器解析到 Node *pnext; 这一行时,它还不知道 Node 是什么类型,所以报错。
}Node;


//方式一:给结构体加标签(最推荐)
typedef struct Node  // 加上标签 "Node"
{
    int data;
    struct Node *pnext;  // 使用 struct Node 而不是 Node
} Node;

//方式二:先声明后定义
typedef struct Node Node;  // 前向声明别名

struct Node                // 正式定义
{
    int data;
    Node *pnext;           // 现在 Node 已经声明过了,可以用了
};
基于 Simulink 的双向 DC/AC 逆变器中 IGBT/MOSFET 寄生参数影响分析实战教程 摘要:本教程详细解析了Simulink中IGBT/MOSFET寄生参数对双向DC/AC逆变器的影响。通过对比理想模型与含寄生参数(如20nH内部电感、50nH回路电感)的仿真,揭示了电压尖峰、高频振荡等实际问题。建模步骤包括搭建基准电路、引入寄生参数、配置高精度求解器(步长10ns),并给出抑制措施:添加RC缓冲电路、调整驱动电阻。关键发现:寄生参数会显著增加开关损耗和EMI噪声,需通过参数扫描优化设计。教程还提供了代数环报错、仿真速度优化等实战技巧,帮助工程师从理想仿真过渡到高保真分析。 阅读详情

相关推荐

安卓直链APK安装拦截全解析:从Play Protect到厂商管控的应对指南

在移动应用分发领域,APK(Android Package)安装是开发者与用户交互的关键环节。其核心原理涉及安卓系统的安全沙箱机制与权限管理体系,旨在保护用户设备免受恶意软件侵害。这一机制的技术价值在于平衡了应用生态的开放性与安全性,但也在应用推广、企业内部分发等场景中带来了挑战。尤其在通过官网、广告等直链渠道分发APK时,常会遇到安装转化率骤降的问题。这背后主要受到Google Play Protect云端扫描、安卓系统安装权限模型演进(如Android 8.0+的安装源授权)以及设备制造商附加安全层(如

weixin_33894640的博客 468

朝花夕拾 · C语言 | 基础篇

你是否曾与C语言初次相遇,许多概念一知半解。如今带你重走来时路,从头梳理语法、指针、内存、结构体等,陪你扫清底层盲区,为嵌入式开发筑牢根基。以此系列博客,记录复盘全过程。

Vvc_Python的博客 390

手把手教你用TUSB2E22中继器实现eUSB2与USB 2.0互转(附实测数据对比)

本文详细介绍了如何利用TUSB2E22中继器实现eUSB2与USB 2.0的高效互转,包括技术背景、硬件设计要点、信号完整性测试方法及故障排查策略。通过实测数据对比,展示了TUSB2E22在信号延迟、功耗和眼图性能上的显著优势,为工程师提供了实用的工程方案。

weixin_29199873的博客 283

朝花夕拾C

偶然见看到这个问题:structure alignment 这些C的问题都是相当基础而且经典的。 然而我在编译的途中,犯了个更加经典的错误,囧~决定重新拾起大一没学好的C,也好好记录下来。 直接拷贝的源代码,就加了一main函数,打印三个struct的size struct X { short s; /* 2 bytes */ /* 2 padding

Make history... 470

保研专业课复习别瞎卷!抓住408和数学重点,用真题反推高效复习路径

本文针对计算机专业保研学生,提出以真题为导向的408专业课和数学高效复习策略。通过构建真题知识图谱、分析题型与难度矩阵,帮助考生精准把握数据结构、操作系统等核心科目的高频考点,如树与图算法、TCP/IP协议栈等,并制定科学的时间分配方案,实现短期内的快速突破。

weixin_27966471的博客 402

KEPServerEX实战:Modbus TCP与RTU双协议配置详解

本文详细解析了如何使用KEPServerEX软件同时配置与管理Modbus TCP和RTU混合网络。通过实战步骤,指导用户建立双协议通道、配置设备与标签,并分享核心的地址映射规则与通讯故障排查技巧,帮助工业自动化工程师高效集成多协议设备,简化数据采集架构。

weixin_29186249的博客 397

朝花夕拾 · C语言 | 数组篇

数组一般形式:类型说明符 数组名 [常量或常量表达式];类型说明符:基本数据类型、构造数据类型(不能是void类型)。说明数组中保存的数据的数据类型。数组名:遵循标识符的命名规则。常量或常量表达式:数组中可以保存的元素的个数。int a[10];sizeof (a);//40字节//32字节//20字节注意:常量表达式中可以包括常量和符号常量,不能包含变量。也就是说,C语言不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。例如,下面这样定义数组是不行的。

Vvc_Python的博客 719

UDS 诊断 - CommunicationControl(通信控制)(0x28)服务 诊断

字节参数名称字节值#1CommunicationControl(通信控制)请求SID0x28#2#3communicationType(通信类型)#4nodeIdentificationNumer(节点标识符)(高位字节)controlType 为 0x04 或 0x05 时,使用该参数#5nodeIdentificationNumer(节点标识符)(低位字节)controlType 为 0x04 或 0x05 时,使用该参数。

耳朵东金子千的博客 1820

朝花夕拾 · C语言 | 指针篇

基类型 *变量名;基类型:该指针指向的空间存储的数据的数据类型:int、char、float 、double 、void、构造数据类型* : 类型说明符,说明后面的变量是一个指针变量名:遵循标识符的命名规则p开头指针变量中保存的地址,是该数据类型的首地址。

Vvc_Python的博客 409

PMP–一、二、三模–分类–13.干系人管理

A:确认是否已制定沟通管理计划,使业务干系人认识到项目的成功之处。B:让业务干系人参加冲刺回顾会议。C:与发起人和关键干系人一起确定产品待办事项列表中的优先要务,以便交付商业利益。D:为关键干系人开展收尾调研。C。

stqer的博客 1418

「HTML和CSS入门指南」hr 标签详解

标签是 HTML5 中用于插入水平分割线的标签,常用于在页面中添加分隔线或者段落之间的分割线。通过灵活运用 标签和属性,我们可以帮助用户更好地理解页面内容,同时也可以美化和装饰页面。在实际应用中需要注意避免过度使用 标签,以使页面看起来简洁明了。

a451319296的博客 7663

朝花夕拾 · C语言 | 内存篇

内存管理

Vvc_Python的博客 466

【Charge】仿真目录

Author: JiJi\textrm{Author: JiJi}Author: JiJi Created Time: 2026.01.20\textrm{Created Time: 2026.01.20}Created Time: 2026.01.20 Modified Time: 2026.01.20\textrm{Modified Time: 2026.01.20}Modified Time: 2026.01.20工作流程材料模型[Charge] 电荷分布与折射率变化理论 [Charge] FDTD

u011699626的博客 314

朝花夕拾 · C语言 | 预处理命令篇

预处理:展开和#相关的代码:展开头文件、展开宏、处理预处理命令编译:将c语言程序转换成汇编指令。汇编:将汇编指令转换成二进制可执行程序链接:负责链接系统的函数/库函数的实现(链接函数)

Vvc_Python的博客 386

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

朝花夕拾 · C语言 | 函数篇

此外 ,%f 不能接收double型,且双引号里写了什么,在输入时也要相同,所以除了格式控制符之外尽可能少写其他数据。八进制与十六进制也可指定输出域宽,如%8o表示输出八位八进制数,%8x表示输出八位十六进制数;此外,%lo与%lx则可表示以八和十六进制输出long型。在输入整型时,可以使用空格,Tab与Enter隔开两数,除此之外用其他字符则会直接中断输入,舍弃后续读入的数字。域宽输出: 7. %nd 以n位域宽输出,若数据大于n位则以实际位数输出,否则左侧补空。

Vvc_Python的博客 349

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

[C语言朝花夕拾] C语言中的命令行输入参数判断

在C语言中,我们的函数入口经常会有: int main(int argc, char** argv) { ... return 0; } 类似这样的传入参数,这类型的参数是为了,用户在利用命令行调用该程序的时候,能够传入适合的参数去控制程序的特定行为。例如,假如现有程序: #include <stdio.h> int main(int argc, char** argv) { printf("number of arg %d\r\n", argc); int i = 0; for

机器学习杂货铺1号店 1879

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

朝花夕拾 · C语言 | 多文件篇

4.在对应的头文件中加extern关键字声明,头文件中全局变量只能声明不能初始化,定义应在.c文件。Makefile:管理代码工程的编译和链接,由make工具进行解释,实现一键化工程的编译和链接。依赖文件(生成目标文件所依赖的源文件):main.c sum.c sub.c ......编译规则:gcc main.c sub.c sum.c ( -o a.out)在头文件的声明里,函数默认为extern,编译器会自动加上。2.如果只是在定义该全局变量的文件中使用该全局变量,可以不声明;

Vvc_Python的博客 394

朝花夕拾 · C语言 | 流程控制篇

if,switch,for,while,do while

Vvc_Python的博客 351

朝花夕拾 · C语言 | 位运算篇

<按位左移 按位左移,低位补0 num << n <===> num *2^n。>>按位右移 按位右移动,有符号数高位补符号位:无符号数高位补0。| 按位或 有1则1,全0为0。~按位取反 1取反为0,0取反为1。1010 0010 //低四位置0。& 按位与 全1为1,有0则0。^ 按位异或 相同为0,相异为1。3.两数交换(不使用中间变量)

Vvc_Python的博客 299

朝花夕拾 · C语言 | 调试篇

l 列出原代码。q 退出gdb。r 运行程序。S 跟进函数。1.编译程序:-g选项:允许使用gdb进行调试。gnu提供的Linux下的代码调试工具。b+行号 在指定行打断点。p+变量名 查看变量值。where 定位段错误的位置。1.使用gdb调试逻辑错误;2.使用gdb调试段错误。gdb./可执行程序。

Vvc_Python的博客 164

[朝花夕拾C语言]:指针的进阶学习

指针到底是个啥呢?在指针里面(1.数组 2.数组指针 3.指针数组 4.函数指针 5.函数指针数组) 的基本概念和应用,如何区分!

qq_44838021的博客 223

C语言一文速成 | 期末保命夺分神器!

用户编程时使用的名字函数声明:在使用函数前,需要声明他的返回类型和参数列表//返回值 函数名(参数列表);函数定义:完整的函数实现,包括函数体。return a+b;数组是一种数据结构,用于存储一组相同类型的数据数组中的元素在内存中是连续存放的数组通过下标来访问元素,下标从0开始。

爱因斯晨的博客 1239

朝花夕拾C语言:用结构体判断某一年的某天是该年多少天?

判断该天是在该年的多少天!!

qq_44838021的博客 287

[朝花夕拾C语言]:排序函数qsort详细讲解

通过对: 1.整型冒泡排序; 2.qsort函数对于排序捷运用,其中通过建立结构体指针,对相同的项进行比较; 3.对sizeof()和stelrn()的基本概念和基本运用的分析。 加深理解!

qq_44838021的博客 570

朝花夕拾C语言:输出字母对应的金字塔

输出字母对应的金字塔

qq_44838021的博客 479

【朝花夕拾C语言】:C语言,猜猜谁是凶手?

详细说明了:四个人当中的凶手该如何进行判断和五个人每个人都只说了一般真话的代码实现!打开新的思路和想法.......

qq_44838021的博客 888
上一篇: 朝花夕拾 · C语言 | 预处理命令篇
下一篇: 朝花夕拾 · C语言 | 内存篇
剑指offer.
博客等级 码龄3年 15粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值