【C语言】21-结构体
C语言的核心部分都说得七七八八了,相信大家已经对C语言的基本数据类型(char\int\float)、数组、指针都很熟悉了,今天来学习C语言中另外一种数据类型:结构体。在iOS开发中,结构体是经常用到的数据类型,使用频率不亚于指针,所以需要重视,不过用法非常简单。
一、什么是结构体
* 在前面的时候已经介绍了C语言中的数组,用法跟其他语言差不多。当一个整体由多个数据构成时,我们可以用数组来表示这个整体,但是数组有个特点:内部的每一个元素都必须是相同类型的数据。
* 在实际应用中,我们通常需要由不同类型的数据来构成一个整体,比如学生这个整体可以由姓名、年龄、身高等数据构成,这些数据都具有不同的类型,姓名可以是字符串类型,年龄可以是整型,身高可以是浮点型。
* 为此,C语言专门提供了一种构造类型来解决上述问题,这就是结构体,它允许内部的元素是不同类型的。
二、结构体的定义
1.定义形式
结构体内部的元素,也就是组成成分,我们一般称为"成员"。
结构体的一般定义形式为:

1 struct 结构体名{
2
3 类型名1 成员名1;
4
5 类型名2 成员名2;
6
7 ……
8
9 类型名n 成员名n;
10
11 };

struct是关键字,是结构体类型的标志。
2.举例
比如,我们定义一个学生
struct Student {
char *name; // 姓名
int age; // 年龄
float height; // 身高
};
上面定义了一个叫做Student的结构体,共有name、age、height3个成员。呵呵,看到这里是否有点面向对象的味道呢,其实这跟面向对象完全是两码事,只能说感觉有点像。
三、结构体变量的定义
前面只是定义了名字为Student的结构体类型,并非定义了一个结构体变量,就像int一样,只是一种类型。
接下来定义一个结构体变量,方式有好多种。
1.先定义结构体类型,再定义变量

1 struct Student {
2 char *name;
3 int age;
4 };
5
6 struct Student stu;

第6行定义了一个结构体变量,变量名为stu。struct和Student是连着使用的。
2.定义结构体类型的同时定义变量
struct Student {
char *name;
int age;
} stu;
结构体变量名为stu
3.直接定义结构体类型变量,省略类型名
struct {
char *name;
int age;
} stu;
结构体变量名为stu
四、结构体的注意点
1.不允许对结构体本身递归定义
如下做法是错误的,注意第3行
1 struct Student {
2 int age;
3 struct Student stu;
4 };
2.结构体内可以包含别的结构体

1 struct Date {
2 int year;
3 int month;
4 int day;
5 };
6
7 struct Student {
8 char *name;
9 struct Date birthday;
10 };

注意第9行
3.定义结构体类型,只是说明了该类型的组成情况,并没有给它分配存储空间,就像系统不为int类型本身分配空间一样。只有当定义属于结构体类型的变量时,系统才会分配存储空间给该变量

1 struct Student {
2 char *name;
3 int age;
4 };
5
6 struct Student stu;

第1~4行并没有分配存储空间,当执行到第6行时,系统才会分配存储空间给stu变量。
4.结构体变量占用的内存空间是其成员所占内存之和,而且各成员在内存中按定义的顺序依次排列
比如下面的Student结构体:
1 struct Student {
2 char *name; // 姓名
3 int age; // 年龄
4 float height; // 身高
5 };
在16位编译器环境下,一个Student变量共占用内存:2 + 2 + 4 = 8字节。
五、结构体的初始化
将各成员的初值,按顺序地放在一对大括号{}中,并用逗号分隔,一一对应赋值。
比如初始化Student结构体变量stu

1 struct Student {
2 char *name;
3 int age;
4 };
5
6 struct Student stu = {"MJ", 27};

struct Student stu;
stu = {"MJ", 27};
六、结构体的使用
1.一般对结构体变量的操作是以成员为单位进行的,引用的一般形式为:结构体变量名.成员名

1 struct Student {
2 char *name;
3 int age;
4 };
5
6 struct Student stu;
7
8 // 访问stu的age成员
9 stu.age = 27;

第9行对结构体的age成员进行了赋值。"."称为成员运算符,它在所有运算符中优先级最高
2.如果某个成员也是结构体变量,可以连续使用成员运算符"."访问最低一级成员

1 struct Date {
2 int year;
3 int month;
4 int day;
5 };
6
7 struct Student {
8 char *name;
9 struct Date birthday;
10 };
11
12 struct Student stu;
13
14 stu.birthday.year = 1986;
15 stu.birthday.month = 9;
16 stu.birthday.day = 10;

注意第14行以后的代码
3.相同类型的结构体变量之间可以进行整体赋值

1 struct Student {
2 char *name;
3 int age;
4 };
5
6 struct Student stu1 = {"MJ", 27};
7
8 // 将stu1直接赋值给stu2
9 struct Student stu2 = stu1;
10
11 printf("age is %d", stu2.age);

注意第9行。输出结果为:
七、结构体数组
1.定义
跟结构体变量一样,结构体数组也有3种定义方式
struct Student {
char *name;
int age;
};
struct Student stu[5]; //定义1
struct Student {
char *name;
int age;
} stu[5]; //定义2
struct {
char *name;
int age;
} stu[5]; //定义3
上面3种方式,都是定义了一个变量名为stu的结构体数组,数组元素个数是5
2.初始化
struct {
char *name;
int age;
} stu[2] = { {"MJ", 27}, {"JJ", 30} };
也可以用数组下标访问每一个结构体元素,跟普通数组的用法是一样的
八、结构体作为函数参数
将结构体变量作为函数参数进行传递时,其实传递的是全部成员的值,也就是将实参中成员的值一一赋值给对应的形参成员。因此,形参的改变不会影响到实参。

1 #include <stdio.h>
2
3 // 定义一个结构体
4 struct Student {
5 int age;
6 };
7
8 void test(struct Student stu) {
9 printf("修改前的形参:%d \n", stu.age);
10 // 修改实参中的age
11 stu.age = 10;
12
13 printf("修改后的形参:%d \n", stu.age);
14 }
15
16 int main(int argc, const char * argv[]) {
17
18 struct Student stu = {30};
19 printf("修改前的实参:%d \n", stu.age);
20
21 // 调用test函数
22 test(stu);
23
24
25 printf("修改后的实参:%d \n", stu.age);
26 return 0;
27 }

* 首先在第4行定义了一个结构体类型Student
* 在第18行定义了一个结构体变量stu,并在第22行将其作为实参传入到test函数
输出结果为:
,形参是改变了,但是实参一直没有变过
九、指向结构体的指针
* 每个结构体变量都有自己的存储空间和地址,因此指针也可以指向结构体变量
* 结构体指针变量的定义形式:struct 结构体名称 *指针变量名
* 有了指向结构体的指针,那么就有3种访问结构体成员的方式
- 结构体变量名.成员名
- (*指针变量名).成员名
- 指针变量名->成员名

1 #include <stdio.h>
2
3 int main(int argc, const char * argv[]) {
4 // 定义一个结构体类型
5 struct Student {
6 char *name;
7 int age;
8 };
9
10 // 定义一个结构体变量
11 struct Student stu = {"MJ", 27};
12
13 // 定义一个指向结构体的指针变量
14 struct Student *p;
15
16 // 指向结构体变量stu
17 p = &stu;
18
19 /*
20 这时候可以用3种方式访问结构体的成员
21 */
22 // 方式1:结构体变量名.成员名
23 printf("name=%s, age = %d \n", stu.name, stu.age);
24
25 // 方式2:(*指针变量名).成员名
26 printf("name=%s, age = %d \n", (*p).name, (*p).age);
27
28 // 方式3:指针变量名->成员名
29 printf("name=%s, age = %d \n", p->name, p->age);
30
31 return 0;
32 }

输出结果:
【C语言】21-结构体的更多相关文章
- C语言利用结构体数组实现学生成绩管理系统
这篇文章主要为大家详细介绍了C语言利用结构体数组实现学生成绩管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 要求: 某班有最多不超过30人(具体人数由键盘输入) ...
- C语言中结构体赋值问题的讨论
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- C语言的结构体和C++结构体的区别
关于C++中声明结构体中需要使用构造器创建实例对象的语法: <C++的结构体构造方法的基本概念:结构体的构造方法需要和结构体的名字相同,并且无返回值,也不要void关键字,这样的方法就是构造器的 ...
- 01.C语言关于结构体的学习笔记
我对于学习的C语言的结构体做一个小的学习总结,总结如下: 结构体:structure 结构体是一种用户自己建立的数据类型,由不同类型数据组成的组合型的数据结构.在其他高级语言中称为记录(record) ...
- C语言中结构体对齐问题
C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...
- 逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式
逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式 一丶了解什么是结构体,以及计算结构体成员的对其值以及总大小(类也是这样算) 结构体的特性 1.结构体(struct)是由一系列具有相同类型或不 ...
- C语言中结构体赋值问题的讨论(转载)
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- go语言学习-结构体
结构体 go语言中的结构体,是一种复合类型,有一组属性构成,这些属性被称为字段.结构体也是值类型,可以使用new来创建. 定义: type name struct { field1 type1 fie ...
- 将c语言的结构体定义变成对应的golang语言的结构体定义,并将golang语言结构体变量的指针传递给c语言,cast C struct to Go struct
https://groups.google.com/forum/#!topic/golang-nuts/JkvR4dQy9t4 https://golang.org/misc/cgo/gmp/gmp. ...
- [日常] Go语言圣经--结构体,JSON习题
Go语言圣经-结构体 1.结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体 2.通常一行对应一个结构体成员,成员的名字在前类型在后,不过如果相邻的成员类型如果相同的话可以被合并到一行 ...
随机推荐
- 推荐一份 Google 面试指南
经常有不少读者在我公众号后台留言,说自己还是应届毕业生,缺乏工作经验与项目经验,不知道如何才能通过面试? 其实,项目经验固然重要,但是企业也知道,对于应届毕业生,是很难有拿得出手的项目经验出来的,毕竟 ...
- jenkins中“Poll SCM”和“Build periodically”的区别
Poll SCM:定时检查源码变更(根据SCM软件的版本号),如果有更新就checkout最新code下来,然后执行构建动作.我的配置如下: */5 * * * * (每5分钟检查一次源码变化) B ...
- Java设计模式之生产者消费者模式
Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...
- windows环境按照dcm4chee
背景: dcm4chee是dcm4che开源项目中的一部分,是一款符合IHE规定的影像管理/归档应用.dcm4chee遵循DICOM.HL7标准,实现了图像存储.图像提取.及健康领域的工作流程管理.d ...
- Cookie && Session之验证实例
为了防止各种自动登录,以及反作弊和破坏,往往会要求登录时让用户输入随机产生的验证码(这组验证码是一组数字和字母),这样可以起到一定的防止他人利用程序让机器自动反复登录的情况.在PHP下要实现这种功能是 ...
- 彻底解决Odoo8.0单时区应用中的时区问题
原文地址:http://shine-it.net/index.php/topic,17001.0.html 由于数据库中存储的是UTC时区,默认情况下数据导出和group by都存在时区问题.彻底解决 ...
- C#-MessageBox全部函数重载形式及举例
Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.D ...
- SQL Server Service Broker 简单例子 (转)
SQL Server Service Broker服务体系结构 消息类型 — 定义应用程序间交换的消息的名称.还可以选择是否验证消息.约定 — 指定给定会话中的消息方向和消息类型.队列 — 存储消息. ...
- 关于使用jquery时,ie8下提示对象不支持的属性或方法的解决办法
转自:http://wapapp.baidu.com/auoong/item/538790fcbe87c834d7ff8cde 首先这个问题的前提是已经排除了常见的这个问题.下面说一种今天我碰到的一种 ...
- Android编译程序报错:Re-installation failed due to different application signatures.
如果机子上已经安装非本机编译的android程序,在编译的时候就会报错.方法首选的是删除原程序,然后再进行编译. 但是有一部分程序是烧录在系统程序里面的,无法直接删除,这时候可以使用adb shell ...