结构体 结构体

结构体类型的声明

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

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

相关推荐
2601_961146204 分钟前
实验室用等离子表面处理设备处理汽车PP内饰件和PBT骨架的一点记录
笔记·汽车·设备
二十七日秋8 分钟前
算法刷题笔记「Day 1|四道 OJ 入门题里的深坑」
c语言·汇编·数据结构·c++·笔记·python·算法
星恒随风22 分钟前
Linux Socket TCP编程(二):逐文件重构多进程、多线程与线程池服务器,深入fork、pthread_create、popen和std::bind
linux·服务器·笔记·学习·tcp/ip
晚风叙码23 分钟前
Linux 进程概念(下):程序地址空间与虚拟内存
linux·服务器·算法
silvamux_42 分钟前
微头条爆款体平台适配实测:把交付要求变成可计算的指标
java·线性代数·算法·决策树·矩阵
abc light1 小时前
ARM 裸机开发(1)——ARM 体系结构
c语言·arm开发
重生之小比特1 小时前
【算法拾光】前缀和|连续的子数组和 + 和相同的二元子数组
算法·leetcode·哈希算法
hkNaruto1 小时前
【AI】深度学习、强化学习、深度强化学习基础概念笔记
人工智能·笔记·深度学习
一去不复返的通信er1 小时前
力扣15:盛最多水的容器
算法·leetcode
Navigator_Z1 小时前
LeetCode //C - 1309. Decrypt String from Alphabet to Integer Mapping
c语言·算法·leetcode