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;
}

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

相关推荐
我爱cope10 分钟前
【计算机网络 | 物理层3:数字编码与调制:比特如何变成可传输的信号?】
网络·学习·计算机网络
小叮当爱咖啡20 分钟前
Day3.参数+Prompt三板斧
开发语言·python·prompt
菜冻鱼26 分钟前
Python-pandas-索引与筛选
开发语言·笔记·python·numpy·pandas·学习方法
一只小菜鸡..36 分钟前
南京大学 操作系统 (JYY) 学习笔记:最终章——操作系统的宇宙,与我们的星辰大海
笔记·学习
鹿角片ljp1 小时前
Java面试复盘(二):String不可变、字符串常量池与字符串拼接
开发语言·python
小秋求学记.2 小时前
PHP安全漏洞实战:从环境配置到RCE攻击
开发语言·php
阿米亚波2 小时前
【C/C++包管理器】vcpkg(by microsoft)
c语言·c++·git·vscode·microsoft·github·vcpkg
看浪的路人2 小时前
第3讲:代码补全引擎
开发语言·windows·python
SNAKEpc121382 小时前
OpenGL(十一)- 变换管线
c语言·c++·算法·矩阵·图形渲染
小小龙学IT2 小时前
Day 26-27 项目实战:从零构建一个高并发聊天室(epoll + 线程池)
linux·服务器·c语言·开发语言·网络