结构体 结构体

结构体类型的声明

写在main函数外面

cpp 复制代码
struct Book{
    char book_name[20];
    char author[20];
    float price;
    char id[19];
}a1,a2,a3;//这里必须要有封号

结构的特殊声明(可以不完全声明)

匿名结构体类型

cpp 复制代码
struct{
    char book_name[20];
    char author[20];
    float price;
    char id[19];
}s1,s2;//只能在这里创建结构体变量

int main(){
    return 0;
}

结构体变量的创建和初始化

cpp 复制代码
struct Book{
    char book_name[20];
    char author[20];
    float price;
    char id[19];
}a1,a2,a3;//这里必须要有封号

int main(){
    struct Book b1 = {"数据结构","lili",18.8f,"91029384020113"};
    struct Book b2 = {.id="ug20260817",.book_name="liliLinux",.author="lili",.price=8.8f};
    struct Book b3;
}

结构的自引用

数据结构:数据在内存中的组织结构

解决的问题:

1.解决 "数据数量不确定" 的问题

2.解决 "数据之间需要动态关联" 的问题

线性的数据结构:

数据在内存中连续存放:顺序表

|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 |

链表:

结点要存放数据,还要找到下一个结点,怎么做到?

Struct Node

{

int data;

struct Node next;

}

不能这样写,会死循环

想找下一个结点,就把下一个结点的地址存放起来就好了

这时候就用指针

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

所以,结构体的自引用:

在一个结构体类型的结构体中,找到下一个同类型的下一个结构体变量。

存放数据的区域:数据域

存放指针的区域:指针域

对结构体类型重命名

typedef struct Node

{

int data;

struct Node* next; //这里面不能用重命名的名称

}Node; //Node就是新命名的

结构体成员访问操作符

1. 点操作符

struct Point p1;

p1.x = 10;

p1.y = 20;

2. 箭头操作符

struct Point *ptr = &p1;

ptr -> x = 30;

ptr -> y = 40;

3. (ptr ->x = 30;) 等效写法

(*ptr).x = 30;

结构体内存对齐(很重要)

用于计算结构体的大小

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
struct s1{
	char c1;
	char c2;
	int n;
};
struct s2 {
	char c1;
	int n;
	char c2;
};
int main() {
	printf("%zd\n", sizeof(struct s1));
	printf("%zd\n", sizeof(struct s2));
}

为什么s1结构体总大小结果是8,s2结果是12 ???

因为结构体在内存中存在对齐现象

这里就要引入偏移量的概念

一个字节是一个内存单元

结构体的对齐规则:

  1. 结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
  3. 结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数,所有对齐数中最大的)的整数倍
  4. 如果嵌套了结构体的備况,歌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

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

  • VS 中默认的值为 8
  • Linux中 goc 没有默认对齐数,对齐数就是成员自身的大小
    offsetof 是宏

用于计算结构体成员相较于结构体变量起始位置的偏移量

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stddef.h>
struct S1{
	char c1;
	char c2;
	int n;
};
struct S2 {
	char c1;
	int n;
	char c2;
};
int main() {
	struct S1 s1 = { 0 };
	printf("%zd\n", offsetof(struct S1,c1));
	printf("%zd\n", offsetof(struct S1,c2));
	printf("%zd\n", offsetof(struct S1,n));
}

结果是0 1 4

结构体总大小:8

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stddef.h>
struct S1{
	char c1;
	char c2;
	int n;
};
struct S2 {
	char c1;
	int n;
	char c2;
};
int main() {
	struct S1 s1 = { 0 };
	printf("%zd\n", offsetof(struct S2,c1));
	printf("%zd\n", offsetof(struct S2,n));
	printf("%zd\n", offsetof(struct S2,c2));
}

结果是0 4 8

结构体总大小:12

目前它们占9个字节,但因为最大对齐数是4,所以结构体总大小为12

为什么存在对齐?

1.平台原因:

某些硬件平台只能在某些地址处访问特定类型的数据

2.性能原因

怎么节省空间?

让占用空间小的成员尽量在一起

or

修改VS上为8的默认对齐数(一般设置为2)

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#pragma pack(1)
struct S{
	char c1;
	int n;
	char c2;
};
#pragma pack()//改为原位
int main() {
	printf("%zd\n", sizeof(struct S));
	return 0;
}

结构体传参

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
struct S{
	int arr[1000];
	int n;
	char ch;
};
void print1(struct S tmp) {//用tmp打印跟用S打印一样
	//传值调用
	for (int i = 0; i < 10; i++) {
		printf("%d ", tmp.arr[i]);
	}
	printf("\n");
	printf("n = %d", tmp.n); 
	printf("\n");
	printf("ch = %c", tmp.ch);
	printf("\n");
}
void print2(struct S* ps) {
	//传址调用
	for (int i = 0; i < 10; i++) {
		printf("%d ", ps->arr[i]);
	}
	printf("\n");
	printf("n = %d", ps->n);
	printf("\n");
	printf("ch = %c", ps->ch);
	printf("\n");
}
int main() {
	struct S s = { {1,2,3,4,5,6,7,8,9,10},10,'w' };
	print1(s);
	print2(&s);
	return 0;
}

结论:结构体传参时,要传结构体的地址

相关推荐
是隼人2 小时前
buuctf-pwn PWN8题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
有Li2 小时前
【AI答疑】MR数据预处理步骤
人工智能·笔记·算法·语言模型·医学生
GG-_-Bond2 小时前
9.1kv存储持久化模拟面试
linux·c语言·数据结构·c++
盛世宏博北京2 小时前
多传感器数据融合算法:实现档案库房温湿度全域无死角监测
算法·档案温湿度
江湖人称菠萝包2 小时前
【Qt】《Qt 5.9 C++开发指南》笔记-Chapter3-Qt类库概述
笔记·qt·qt5
无敌贵点大王3 小时前
RTThread学习记录10——C语言实现面向对象的编程
c语言·stm32·学习·链表
AgentMaster3 小时前
零售行业智能客服系统怎么选?3 大场景落地与 4 款平台对比实践
大数据·人工智能·算法
江屿风3 小时前
【Linux系统】【Linux进程终止等待详解与程序替换机制初体验】流食般投喂
linux·运维·笔记·系统架构·centos·unix
远航计算机3 小时前
客服记录怎么变成 AI 会引用的内容?五步清洗法
大数据·人工智能·算法·aigc