广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言 struct结构体超详细讲解
  • 570
分享到

C语言 struct结构体超详细讲解

2024-04-02 19:04:59 570人浏览 泡泡鱼
摘要

目录一、本章重点二、创建结构体三、typedef与结构体的渊源四、匿名结构体五、结构体大小六、结构体指针七、其他一、本章重点 创建结构体typedef与结构体的渊源匿名结构体结构体大

一、本章重点

  • 创建结构体
  • typedef与结构体的渊源
  • 匿名结构体
  • 结构体大小
  • 结构体指针
  • 其他

二、创建结构体

先来个简单的结构体创建

这就是一个比较标准的结构体

struct people
{
	int age;
	int id;
	char address[10];
	char sex[5];
};//不要少了分号。

需要注意的是不要少了分号。

那么这样创建结构体呢?

struct phone
{
	char brand[10];//品牌
	int price;//价格
};
 
struct people
{
	int age;
	int id;
	char address[10];
	char sex[5];
	struct phone;
};

很显然,一个结构体是能够嵌套另一个结构体的。

没有这样的设计,这样做也行

struct people
{
	int age;
	int id;
	char address[10];
	char sex[5];
	char phone_brand[10];
	int phone_price;
};

但结构体中成员太多了是不利于我们后期的维护的,试问:假设有1000个成员,你能快速的找出你需要的成员吗?当有了分块的结构体,我们是能够迅速的定位和查看的。

?结构体能够嵌套另一结构体,那么结构体能否嵌套自己呢?

struct phone
{
	char brand[10];
	int price;
	struct phone;
};

这样做之后编译器会给你一个报错

原因是什么呢?

因为这个结构体的大小是未定义的,你能算出这个结构体的大小吗?这是不可能的!

既然大小不能确定,那么当你用这个结构体去创建变量,编译器该为这个变量开辟多大的空间呢?所有编译器在设计之初便杜绝了这种可能。

在提一个问题,结构体是否可以嵌套自己的结构体指针呢?

struct people
{
	int age;
	int id;
	char address[10];
	char sex[5];
	struct people* son[2];
};

答案是:可以

这里并不存在空间该分配多少的问题,因为struct people*是指针类型,它的大小是确定的,在32位机器下是4字节,64为机器是8字节。

三、typedef与结构体的渊源

先上一段代码

struct people
{
	int age;
	int id;
}a;//a代表什么?
 
 
int main()
{
	a.age = 20;
	printf("%d\n", a.age);
	return 0;
}

提问:a代表什么?

其实我们可以这样去看这个问题

struct people{int age;int id;} a;
 
 
int main()
{
	a.age = 20;
	printf("%d\n", a.age);
	return 0;
}

对比int b呢?

int b;
struct people{int age;int id;} a;
 
 
int main()
{
	a.age = 20;
	printf("%d\n", a.age);
	return 0;
}

显然,struct people{int age;int id;}代表的是结构体类型,就像整形类型一样去创建变量。

那么这里的a就是结构体创建的变量。

这里也能明白结构体创建的最后为什么要保留分号。

那我们再看一段代码:

typedef struct people
{
	int age;
	int id;
}a;
 
 
int main()
{
	a.age = 20;
	printf("%d\n", a.age);
	return 0;
}

此时加上typedef,a还能当结构体创建的变量吗?

显然不行,此时编译器会报错。

 理解方式以上述一致。

typedef struct people{int age;int id;} a;

类似于

typedef struct people{int age;int id;} a;
typedef int b;

此时的a就是struct people{int age;int id;}

typedef的作用是把struct people{int age;int id;}这一类型重命名为a。

不知道你有没有见过这样的代码

typedef struct people
{
	int age;
	int id;
}b,a,*c;
 
int main()
{
	a a1;
	b b1;
	c c1 = &a1;
	a1.age = 5;
	b1.age = 6;
	c1->age = 10;
	printf("%d %d %d\n", a1.age, b1.age, c1->age);
	return 0;
}

你知道运行结果吗?

这里的b、a、c是什么呢?

这里我就不啰嗦了,a和b都是struct people{int age;int id;}结构体类型,c是struct people{int age;int id;}*  结构体指针类型。

运行结果:

那么再次提升一下

typedef struct people
{
	int age;
	int id;
}b, a, c[20];
这里的b、a、c代表什么呢?

期待着你动手解决这一问题。

四、匿名结构体

这就是一个匿名的结构体

struct
{
	int age;
	int id;
};
 
int main()
{
	struct p1;
	p1.age = 10;
	printf("%d\n", p1.age);
	return 0;
}

匿名结构体能这样创建结构体变量吗?

此时编译器会报错

这样的匿名结构体只能在创建结构体的时候定义好变量。

比如这样

struct
{
	int age;
	int id;
}p1;
 
int main()
{
	p1.age = 10;
	printf("%d\n", p1.age);
	return 0;
}

 接下来我们看下这段代码

typedef struct
{
	int age;
	int id;
}people;
 
int main()
{
	people p1;
	p1.age = 10;
	printf("%d\n", p1.age);
	return 0;
}

这里我们重命名这个匿名结构体,即把这个结构体类型重命名为people。

那么我们自然可以用people类型来创建p1。也可创建p2、p3等等。

运行结果:

以下代码合法吗?

//匿名结构体类型
struct
{
 int a;
 char b;
 float c; 
}x;
 
struct
{
 int a;
 char b;
 float c; 
}a[20], *p;
 
int main()
{
    //在上面代码的基础上,下面的代码合法吗?
    p = &x;
    return 0;
}

警告: 编译器会把上面的两个声明当成完全不同的两个类型。 所以是非法的。

五、结构体大小

如何求结构体类型的大小?

这需要了解结构体成员在内存是怎么存储的。

你知道下面这段代码的运行结果吗?

struct people
{
	char a;
	int b;
	char c;
};
 
int main()
{
	struct people p1;
	printf("%d\n", sizeof(p1));//大小是6吗?
	return 0;
}

char是一字节大小

int是四字节大小

char是一字节大小

直接相加等于6

那么这个结构体的大小是6吗?

但我们发现答案是12

这是为什么呢?

简单来说编译器为了读取内存时提升效率和避免读取出错,它做了内存对齐的操作。

什么是内存对齐?

就是让数据安排在合适的位置上所进行的对齐操作。

为什么要内存对齐?

  • 一、移植原因

1.不是所有的硬件平台都能访问任意地址上的任意数据的;

2.某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

  • 二、性能原因:

为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

对齐规则:

windows中默认对齐数为8,linux中默认对齐数为4

  • 一:第一个数据成员从偏移地址为0的地方开始存放。
  • 二:对齐数:等于默认对齐数与与该成员大小的较小值。
  • 三:从第二成员开始,从它对齐数的整数倍的偏移地址开始存放。
  • 四:最后结构体的大小需要调整为最大对齐数的整数倍。

最大对齐数:即所有成员对齐数中最大的对齐数。

struct people
{
	char a;
	int b;
	char c;
};

解析:

第一个为char,直接放在偏移地址为0的位置处。

第二个为int,它的自身大小为4,比默认对齐数小,所以它的对齐数是4。

4是4的整数倍,所以在偏移地址为4处开始放数据。

第三个为char,自身大小为1,比默认对齐数小,它的对齐数是1。

8是1的整数倍,从偏移地址为8的位置开始放。

总大小为9,不是最大对齐数的整数倍

要浪费3个空间,调整后为12。

我们再看看下面这段代码:

将char 和 int成员变量交换位置后,这结构体的大小还是12吗?

struct people
{
	char a;
	char c;
	int b;
};
 
int main()
{
	struct people p1;
	printf("%d\n", sizeof(p1));//大小是多少呢?
	return 0;
}

解析:

第一个:直接从0处开始放

第二个是char:对齐数是1,1是1的整数倍,从偏移地址为1的位置开始放。

第二个是int:对齐数是4,4是4的整数倍,从偏移地址为4的位置开始放。

放好各个成员变量后,总大小是8,是最大对齐数(4)的整数倍,不需要调整。

因此这个结构体的大小是8.

再来看看下面这个如何?

struct people
{
	char a;
	int b;
	short c[2];
	char d;
};
 
int main()
{
	struct people p1;
	printf("%d\n", sizeof(p1));//大小是6吗?
	return 0;
}

解析:

第一个成员是char,直接放再0地址处。

第二个成员是int,对齐数是4,从偏移地址为4的位置处开始存放。

第三个成员是short[2],关于数组,它的对齐数是首元素的大小与默认对齐数的较小值,这里它的对齐数是2,然后从偏移地址为8处开始存放4个字节。

第四个成员是char,对齐数是1,直接放开12位置处。

总大小是13,最大对齐数是4,不是最大对齐数的整数倍,需要对齐到最大对齐数的整数倍,浪费3字节大小,对齐到16.

所以这个结构体的大小是16.

六、结构体指针

先创建一个结构体

struct people
{
	char a;
	int b;
};

然后用该结构体创建变量,再用结构体指针指向该变量。

int main()
{
	struct people p1;
	struct people* p = &p1;
	return 0;
}

所谓结构体指针,即指向结构体的指针。

正如整形指针,即指向整形的指针。

访问变量方式1:

int main()
{
	struct people p1;
	struct people* p = &p1;
	p1.a = 'a';
	p1.b = 10;
	printf("%c %d\n", p1.a, p1.b);
	return 0;
}

访问变量方式2:

int main()
{
	struct people p1;
	struct people* p = &p1;
	p->a = 'a';
	p->b = 10;
	printf("%c %d\n", p->a, p->b);
	return 0;
}

访问变量方式3:

int main()
{
	struct people p1;
	struct people* p = &p1;
	(*p).a = 'a';
	(*p).b = 10;
	printf("%c %d\n", (*p).a, (*p).b);
	return 0;
}

七、其他

结构体中还有两个常见知识点:

一、位端

二、柔性数组

由于篇幅原因,下期会细细讲解这两个知识点

到此这篇关于C语言 struct关键字超详细讲解的文章就介绍到这了,更多相关C语言 struct内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言 struct结构体超详细讲解

本文链接: https://www.lsjlt.com/news/145639.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言 struct结构体超详细讲解
    目录一、本章重点二、创建结构体三、typedef与结构体的渊源四、匿名结构体五、结构体大小六、结构体指针七、其他一、本章重点 创建结构体typedef与结构体的渊源匿名结构体结构体大...
    99+
    2022-11-13
  • C语言结构体(struct)的详细讲解
    目录引言1. 动态内存管理2. 结构体2.1 定义语法2.2 定义示例2.3 初始化2.4 结构体赋值2.5 结构体数组2.6 结构体指针赋值3. 学生管理系统附:结构体变量的存储原...
    99+
    2022-11-13
  • C语言结构体超详细讲解
    目录前言1、结构体的声明1.1 结构的基础知识1.2 结构的声明1.3 结构成员的类型1.4 结构体变量的定义和初始化2、结构体成员的访问2.1 点操作符访问2.2 ->操作符...
    99+
    2022-11-13
  • C语言超详细讲解指针与结构体
    目录本节目标初识指针1、内存与地址2、变量的地址3、指针变量4、指针的使用5、指针变量的大小初识结构体1、什么是结构体2、结构体的定义3、结构体的使用本节目标 理解内存与地址的相关概...
    99+
    2022-11-13
  • C语言结构体struct详解
    目录结构体的概念结构体类型的声明结构体变量的创建typedef关键字结构体的嵌套结构体变量的初始化结构体成员的访问结构体的传参总结结构体的概念 结构体是由一系列具有相同类型或不同类型...
    99+
    2022-11-13
  • C语言之结构体(struct)详解
    目录为什么需要引入结构体struct定义typedef与#define结构体变量初始化及成员访问结构体访问总结为什么需要引入结构体 原有的数据类型不能满足需求,因此才设计了构造类型结...
    99+
    2022-11-12
  • C语言结构体嵌套与对齐超详细讲解
    目录嵌套结构体结构体内存对齐32位的操作系统64位的操作系统嵌套结构体 格式:typedef struct 结构体名 {struct 结构体名1 结构体变量名1;struct 结构体...
    99+
    2022-12-26
    C语言结构体嵌套 C语言结构体对齐 C语言结构体嵌套与对齐
  • C语言超详细讲解结构体与联合体的使用
    目录结构体offsetof-宏位段枚举联合体(共用体)结构体 结构体内存对齐问题: 当我们在计算结构体的大小时,我们便需要清楚的知道结构体内存对齐是什么。 存在内存对齐的原因可细分为...
    99+
    2022-11-13
  • C语言数据结构超详细讲解单向链表
    目录1.链表概况1.1 链表的概念及结构1.2 链表的分类2. 单向链表的实现2.1 SList.h(头文件的汇总,函数的声明)2.2 SList.c(函数的具体实现逻辑)2.2.1...
    99+
    2022-11-13
  • C语言struct结构体介绍
    目录structstruct的嵌套实验struct C 语言没有其他语言的对象(object)和类(class)的概念,struct 结构很大程度上提供了对象和类的功能。 下面是st...
    99+
    2022-11-13
  • C语言超详细讲解数据结构中的线性表
    目录前言一、分文件编写1、分文件编写概念2、代码展示二、动态分布内存malloc1、初识malloc2、使用方法三、创建链表并进行增删操作1、初始化链表2、在链表中增加数据3、删除链...
    99+
    2022-11-13
  • C语言之结构体定义typedef struct用法详解
    在C语言中,使用struct关键字可以定义一个结构体类型,用于存储不同类型的数据。为了方便使用,可以使用typedef关键字给结构体...
    99+
    2023-08-09
    C语言
  • C语言结构体详细图解分析
    目录结构体结构体的声明结构体变量的定义和初始化结构体大小计算结构体 结构是一些值的集合,这些值称为成员变量。结构的每个成员是不同类型的变量。 为什么要有结构体 比如说,描述一个学生时...
    99+
    2022-11-13
  • C语言超详细讲解线性表
    目录1. 顺序表1.1 管理结点1.2 顺序表的插入1.3 顺序表的删除1.4 顺序表的扩容2. 链表2.1 定义2.2 头部插入2.3 尾部插入2.4 任意位置插入2.5 任意位置...
    99+
    2022-11-13
  • C语言超详细讲解库函数
    目录1 返回整数的getchar函数2 更新顺序文件3 缓冲输出与内存分配4 库函数练习1 返回整数的getchar函数 代码: #include<stdio.h> ...
    99+
    2022-11-13
  • C语言 超详细讲解链接器
    目录1 什么是链接器2 声明与定义3 命名冲突3.1 命名冲突3.2 static修饰符4 形参、实参、返回值5 检查外部类型6 头文件1 什么是链接器 典型的链接器把由编译器或汇编...
    99+
    2022-11-13
  • C语言数组超详细讲解上
    目录前言1、一维数组的创建和初始化1.1 一维数组的创建1.2 一维数组的初始化1.3 一维数组的使用1.4 一维数组在内存中的存储2、二维数组的创建和初始化2.1 二维数组的创建2...
    99+
    2022-11-13
  • C语言中结构体struct怎么对齐
    这篇文章主要介绍“C语言中结构体struct怎么对齐”,在日常操作中,相信很多人在C语言中结构体struct怎么对齐问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言中结构...
    99+
    2022-10-18
  • C语言的struct结构体怎么创建
    本篇内容主要讲解“C语言的struct结构体怎么创建”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言的struct结构体怎么创建”吧!一、本章重点创建结构体typedef与结构体的渊源匿名结...
    99+
    2023-06-30
  • C语言超详细讲解轮转数组
    目录题目描述实例解题思路1. 先整体逆转2.逆转子数组[0, k - 1]3.逆转子数组[k, numsSize - 1]易错点代码题目描述 给你一个数组,将数组中的元素向右轮转 k...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作