C语言-结构体详解

一.什么是结构体以及结构体的声明

1.1什么是结构体?

C语言提供了许多变量的类型,例如:char,short,long,int,float,double,等等,但是如果我想描述一个学生,一本书的时候,单一的内置变量是不够的。因为描述一个学生需要他的名字,年龄,学号,身高,体重等个人信息;要描述一本书的话则需要书名,书的作者,出版社,价格等信息。C语言为了解决这种问题,增加了结构体这种自定义的数据类型。让编程者可以自己定义想要的类型。总的来说,结构体就是一些值的集合,这些值成为成员变量。结构的每个成员可以是不同的类型,如:变量,数组,指针,甚至是其他结构体。

1.2结构体的声明

(1)普通声明:

复制代码
struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}; //分号不能丢

(2)匿名结构体

复制代码
struct
{
	int a;
	char b;	
	float c;
}x;

注意:定名结构体只能用一次!所以最好不用!

(3)结构体的自引用

在数据结构中有线性结构和树形结构,在线性结构中有一种数据结构叫做链表,与顺序表连续存储的方式不同,它采用的是链式存储,当我们在链表中想让从一个节点找到另一个节点是,我们就要用到结构体的自引用。

在结构体中包含一个类型为结构体本身的成员是否可以呢?

比如,定义一个链表节点:

复制代码
struct Node
{
	int data;
	struct Node next;
};

答案是不行,因为如果一个结构体内包含一个相同类型的结构体,那么这个结构体的类型将会是无限大。

所以,正确的写法应该是:

复制代码
struct Node
{
	int data;
	struct Node* next;
};

二.结构体的访问

2.1直接访问:结构体变量.成员名。

复制代码
#include <stdio.h>
struct Point
{
    int x;
    int y;
};
int main()
{
    struct Point a = { 1, 2 };
    printf("x: %d y: %d\n", a.x, a.y);
    return 0;
}

2.2间接访问:结构体指针-> 成员名

复制代码
#include <stdio.h>
struct Point
{
	int x;
	int y;
};
int main()
{
	struct Point p = { 3, 4 };
	struct Point* ptr = &p;
	ptr->x = 10;
	ptr->y = 20;
	printf("x = %d y = %d\n", ptr->x, ptr->y);
	return 0;
}

三.内存对齐问题(计算结构体大小)

3.1对齐规则

(1)结构体的第一个成员对其齐到和结构体变量起始位置偏移量为0的地址处。

(2)从第二个成员变量开始,都要对齐到某个对齐数的整数倍地址处。

对齐数 = 编译器中默认的一个对齐数与该成员变量大小的较小值。

vs中默认值为8,linux中gcc没有默认对齐数,对齐数就是变量成员自身的大小。

(3)结构体总大小为最大对齐数的整数倍。

(4)如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

3.2总的来说结构体内存对齐是那时间换空间的做法。

3.3修改默认对齐数

#pragma这个预处理指令可以帮助我们修改默认对齐数。

3.4结构体传参:结构体传参最好用指针传参!

复制代码
include <stdio.h>

// 定义一个简单的结构体
struct Point {
    int x;
    int y;
};

// 方式1:值传递(拷贝一份,不影响原数据)
void printPoint(struct Point p) {
    printf("x=%d, y=%d\n", p.x, p.y);
}

// 方式2:指针传递(可以修改原数据)
void movePoint(struct Point* p) {
    p->x += 10;  // 修改原数据
    p->y += 10;
}

int main() {
    struct Point p1 = { 3, 5 };

    // 值传递
    printPoint(p1);  // 输出: x=3, y=5

    // 指针传递(修改原数据)
    movePoint(&p1);  // 传入地址
    printPoint(p1);  // 输出: x=13, y=15

    return 0;
}

如果有错误的地方,欢迎大家批评指正!

相关推荐
H.莓飛7 小时前
【数据结构】二叉树_OJ题
linux·开发语言·数据结构·算法
kkkkkkkkkk_Z8 小时前
新手自学嵌入式 | 学习日记:异常与中断基础、i.MX6ULL裸机开发环境搭建、GPIO模块与点灯原理
学习
零基础1238 小时前
Ubuntu 常用命令汇总
linux·运维·开发语言
外收内放8 小时前
Python基础语法练习题(57-58)
开发语言·python
时间的拾荒人8 小时前
Qt 界面美化实战:QSS 样式表
开发语言·qt·面试
杨运交9 小时前
[076][核心模块]构建优雅的Java异常处理框架:从错误码到全局异常处理
java·开发语言
m4Rk_9 小时前
【论文阅读】Agent 记忆机制(94):MemGen——在推理过程中动态生成并织入潜在记忆
论文阅读·人工智能·学习·开源·github
晓德9 小时前
0、LLM大模型安全学习系列(启)
学习·安全
可乐鸡翅yeah_9 小时前
video.js 集成 hls.js 开发 M3U8 播放器,新手高频踩坑
开发语言·前端·javascript·后端·ecmascript·m3u8·音视频在线播放
小鹿的周先生9 小时前
第11章-Structured-Output
开发语言·人工智能·python