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

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

相关推荐
梅雅达编程笔记1 小时前
编程启蒙|Scratch 转 Python 系列第9天:字典/哈希表积木双向对照(AI大模型参数配置表实战)
开发语言·人工智能·python·numpy·pandas
持力行1 小时前
C++与Java变量声明、定义及内存分配的核心区别
java·开发语言·c++
Rainy Blue8832 小时前
C转C++速成
c语言·c++·算法
天选之子1232 小时前
DuckDB学习
jvm·学习
jinyishu_2 小时前
C++ 继承全解:从基础到高级特性
开发语言·c++
一只小菜鸡..3 小时前
Stanford CS144 学习笔记 (四):网络拥塞控制与 AIMD 算法
网络·笔记·学习
xuhaoyu_cpp_java4 小时前
SpringBoot学习(四)
java·经验分享·spring boot·笔记·学习
exm-zem4 小时前
从C语言到C++:C++入门1
c语言·c++
蜡台4 小时前
通过Gradle脚本声明更改Java变量
android·java·开发语言·python·kotlin·gradle·groovy