IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c语言入门-自定义类型-结构体 -> 正文阅读

[C++知识库]c语言入门-自定义类型-结构体

目录

1.结构体概念

2.结构体类型的定义

3.结构体类型变量的声明

4.结构体的嵌套

5.结构体变量的初始化和赋值

6.结构数组

7.结构指针变量说明和使用

8.结构体内存对齐

??9.内存对齐的必要性

?10.修改默认对齐数

?11.结构体变量传参

12.位段


1.结构体概念

结构体是由一批数据组合而成的结构型数据。组成结构型数据的每个数据称为结构型数据的“成员”。每一个成员可以是一个基本数据类型或者是一个构造类型。

2.结构体类型的定义

1.定义一个结构体类型的一般形式为

struct 结构名

{

成员列表;

}

?比如:book称为结构名,该结构有两个成员变量,arr和name。

struct book
	{
		int arr;
		char name[10];
	};

2、定义结构体类型的第二种形式 ? ? ? ? ?

struct 结构名{

成员列表;

}变量列表;? ?? ? ? ? ? ?

#include<stdio.h>
struct book
{
	int price;
	char name[10];
}b1, b2;
struct book b3;
int main()
{
	struct book b4;
	return 0;
}

?b1,b2,b3完全等价,是全局变量,b4是局部变量。

3.结构体类型变量的声明

结构体不会占据空间,结构体变量才会占据空间。

1.先定义结构体,然后定义结构体类型变量

#include<stdio.h>
struct book
{
	int price;
	char name[10];
};
int main()
{
	struct book b1 ;
	return 0;
}

2.定义结构体类型的时候同时声明结构体变量

#include<stdio.h>
struct book
{
	int price;
	char *name;
}b1, b2;

3.匿名结构体类型:省略结构名,定义结构体变量

#include<stdio.h>
struct 
{
	int price;
	char *name;
}b1, b2;

4.结构体的嵌套

1.嵌套其他的结构体

struct custmer
{
	char* name;
	int age;
};
struct book
{
	int price;
	char* name;
	struct custmer x;
}b1, b2;

customer是一个结构,这个结构有两个成员name和age。book是一个结构,b1,b2是book的结构体变量,有三个成员,price,name,x,其中x是custmer结构类型。

2.结构体类型的自引用:使用指针

struct book
{
	int price;
	char* name;
	struct book *next;
    struct book next;//error 结构体的大小无限大
};

5.结构体变量的初始化和赋值

1.结构体变量的初始化用{}

#include<stdio.h>
struct point
{
	int x;
	int y;
}p1 = { 8,9 }, p2 = { 3,8 };
struct ps
{
	double y;
	struct point m;
}m = { 2.34,{3,7} };
int main()
{
	struct point p3 = { 2,4 };
	struct ps p = { 2.34,{3,7} };
	return 0;
}

2.结构体变量的赋值

对成员变量进行逐一赋值

#include<stdio.h>
struct point
{
	int x;
	int y;
}p;
struct ps
{
	double y;
	struct point m;
	char name[10];
}k;
int main()
{
	p.x = 10;
	p.y = 20;
	printf("%d\n", p.x);
	printf("%d\n", p.y);
	k.m.x = 30;
	k.m.y = 24;
	scanf("%s", &k.name);
    //	k.name = "hi";         //error
	// 字符数组只有在定义的时候可以使用=对字符数组赋值,其余情况都不可以
	//char arr[10] = "hi";    正确  
	//char brr[10];brr = "ji"; 错误
	printf("%d\n", k.m.x);
	printf("%d\n", k.m.y);
	printf("%s", k.name);
		return 0;
}

6.结构数组

#include<stdio.h>
struct book
{
	int price;
	char name[20];
}s[3] = {
	{50,"哈利波特"},{20,"英语"},{30,"数学"}};
int main()
{
	s[2].price = 100;
	strcpy(s[2].name, "喵星人");
	for (int i = 0; i < 3; i++)
	{	printf("%d\n", s[i].price);
	    printf("%s\n", s[i].name);
	}
	return 0;
}

7.结构指针变量说明和使用

1.指向结构体变量的指针

#include<stdio.h>
struct book
{
	int price;
	char name[20];
};
int main()
{
	struct book s = { 100,"哈利波特" };
	struct book* p = &s;//p是结构体类型的指针
	printf("%s\n", p->name);
	printf("%d\n", p->price);
	printf("%s\n", (*p).name);
	printf("%d\n",(*p).price);
	return 0;
}

2.访问成员的方式

(*结构指针变量).成员名

结构指针变量->成员名

?3.指向结构数组的指针

#include<stdio.h>
struct book
{
	int price;
	char name[20];
}s[3] = {
	{50,"哈利波特"},{20,"英语"},{30,"数学"} };
int main()
{
	struct book* p = s;//p指向了结构体数组
	for (int i = 0; i < 3; i++)
	{
		printf("%d\n", (p + i)->price);
		printf("%s\n", (p + i)->name);
	}
	return 0;
}

8.结构体内存对齐

结构体内存对齐原则

  • 结构体变量的第一个成员永远放置在结构体偏移量为0的位置
  • 变量从第二个成员开始,放置位置的偏移量是对齐数的整数倍?对齐数:成员类型的字节数和默认对齐数的最小值? ??Linux没有默认对齐数 vs的默认对齐数是8
  • 结构体的总大小必须是各个成员中最大对齐数的整数倍
  • 如果说存在嵌套了结构体类型,那么这个结构体类型对齐到自己的最大对齐数的整数倍,整个结构体类型的总大小是自己最大对齐数(包括嵌套结构体类型)的整数倍

?例题1:


#include<stdio.h>
struct book
{
	char a;
	int b;
	short c;
}s;
int main()
{
	printf("%d ", sizeof(s));
	return 0;
}

?例题2:


#include<stdio.h>
struct book
{
	char a;
	short c;
	int b;
}s;
int main()
{
	printf("%d ", sizeof(s));
	return 0;
}

?例题3:

#include<stdio.h>
struct book
{
	double l;
	char a;
	int b;
}s;
int main()
{
	printf("%d ", sizeof(s));
	return 0;
}

?例题4:

#include<stdio.h>
struct book
{
	char a;
	int b;
	struct book* next;
}s;
int main()
{
	printf("%d ", sizeof(s));
	return 0;
}

?例题5:

#include<stdio.h>
struct book
{
	char a;
	int b;
	char arr[5];
}s;
int main()
{
	printf("%d ", sizeof(s));
	return 0;
}

?例题6?

#include<stdio.h>
struct point
{
	char a;
	int s;
};
struct book
{
	char a;
	short b;
	struct point c;
}s;
int main()
{
	printf("%d ", sizeof(s));
	return 0;
}

?例题7

#include<stdio.h>
struct point
{
	char a;
	int s;
};
struct book
{
	char a;
	short b;
	struct point *c;
}s;
int main()
{
	printf("%d ", sizeof(s));
	return 0;
}

?9.内存对齐的必要性

1.硬件原因:某一些硬件只可以读取特定位置上的特定类型数据,否则硬件错误。

2.性能原因:数据结构(尤其是栈)应该尽可能的在自然边界对齐

对于某一些没有对齐的数据,有可能要读取两次,对齐的数据读取一次就可以了。

内存对齐以空间换取时间

减少空间浪费:让小字节的数据靠在一起

?10.修改默认对齐数

#pragma pack()

#include<stdio.h>
#pragma pack(4)//设置默认对齐数
struct point
{
	short s;
	double k;
};
struct book
{
	char a;
	short b;
	struct point c;
}s;
#pragma pack()//让默认对齐数还原为系统默认对齐数
int main()
{
	printf("%d ", sizeof(s));
	return 0;
}

?11.结构体变量传参

传值调用 传址调用

#include<stdio.h>
struct book
{
	int a[10];
	char name[20];
}b = { {1,2,3,4,5,6,7,8,9,10},"hello" };
void print(struct book s)
{
	for (int i = 0; i < 10; i++)
		printf("%d ", s.a[i]);
	printf("\n%s", s.name);
}
void change(struct book *s)
{
	memset(s->a, 0, 40);
	strcpy(s->name, "hi");
}
int main()
{
	change(&b);
	print(b);
	return 0;
}

12.位段

1.位段

概念:位段,C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或”位域"?。利用位段能够用较少的位数存储数据。

作用:减少存储数据的位数,按照二进制位(比特位)来作为单位长度。

声明:在声明时,位段成员必须是整形或枚举类型(通常是无符号类型),且在成员名的后面是一个冒号和一个整数,整数规定了成员所占用的位数。?

空间开辟:位段的空间上是按照需要以 4 个字节( int )或者 1 个字节( char )的方式来开辟的。
位段涉及很多不确定因素,位段是不跨平台的。
以下是vs-2019的计算方式分析:当空间可以容纳下一个成员时,继续存储,如果说容纳不了,那么剩余空间浪费,重新申请空间。
例题1:结果s占据8个字节
#include<stdio.h>
struct a
{
	int a : 3;
	int m : 20;
	int b : 30;
}s={0};

int main()
{
	s.a = 10;
	s.m = 3;
	s.b = 4;
	printf("%d", sizeof(s));
	return 0;
}

?

?例题2:结果s占据3个字节

#include<stdio.h>
struct a
{
	char a : 3;
	char m : 4;
	char b : 5;
	char n : 4;
}s = { 0 };
int main()
{
	s.a = 10;
	s.m = 3;
	s.b = 4;
	s.n = 8;
	printf("%d", sizeof(s));
	return 0;
}

???2.位段的跨平台问题

1.? 位段被当成有符号数还是无符号数是不确定的。
2. 位段中最大位的数目不能确定。(16位机器int是2个字节,最大值是16,32位机器int是4字节,使用bite位的最大值32)
3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。
总结:位段和结构体作用类似,只是会减小空间的浪费,但是有跨平台问题。
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-24 10:21:36  更:2021-09-24 10:22:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:19:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码