【C语言笔记】struct结构体变量的用法

我们都知道C语言中变量的类型决定了变量存储占用的空间。当我们要使用一个变量保存年龄时可以将其声明为int类型,当我们要使用一个变量保存某一科目的考试成绩时可以将其声明为float。

那么,当我们要做一个学生信息管理系统时,需要保存学生的姓名、学号、年龄等信息,该怎么做呢?
是不是这样定义

zhangsan.name=Liuyao
zhangsan.nam=520
zhangsan.age=24

但是zhangsan.name这个东西我们可是没有学过啊!
所以就出现了结构体

什么是结构体?

结构体(struct)是由一系列具有相同类型或不同类型的数据项构成的数据集合,这些数据项称为结构体的成员。如上面的student结构体包含三个成员,分别是name、num、age。结构体是C语言中的一种构造类型。C语言的数据类型如下图:

一、定义结构体的一般形式

  struct 结构名
{
  成员列表;
};

成员列表的形式为 类型说明符 成员名;

举个例子1
struct student
{
    char *name;  // 学生名字
    int num;     // 学生学号
    int age;     // 学生年龄
};

1.此处,student是结构体名,该名字是由任意定义的,但是尽量起个有意义的名称。其相当于一个模板,可以使用这个模板去定义变量student1, student2, student3。定义的时候不要忘了struct。

2.使用该结构体创建三个变量student1, student2, student3
struct student student1, student2, student3;
定义了student1、student2、student3为struct student 类型的变量,即它们具有了struct student类型的结构。显然,此方法更清晰,因为它把name、num、age都集成在一个模板,要用的时候只要套用模板进行创建即可。这就是结构体。

初始化结构体

现在我们把student1信息表示出来

struct     student   student1 { "20161111","man",18,"zhangsan",90};
类型名     结构体名    变量名
  • 简而言之,我们使用在一对花括号中括起来的初始化列表进行初始化,各初始化项用逗号分隔。

  • 为了让初始化项与结构中各成员的关联更加明显,我们让每个成员的初始化项独占一行。这样做只是为了提高代码的可读性,对编译器而言,只需要用逗号分隔各成员的初始化项即可。

C99和C11为结构提供了指定初始化器(designated initializer)。其初始化器使用点运算符和成员名。例如,只初始化student结构中的name成员,可以这样做:

struct student student1 =
{
   .name = "Liuyao"
};

也可以按照任意顺序使用指定初始化器:

struct student student1 =
{
   .age = 24,
   .num = 520,
   .name = "Liuyao"
};

另外,对特定成员的最后一次赋值才是它实际获得的值。例如,考虑如下代码:

struct student student1 =
{
  .num = 520,
  .name = "Liuyao"1314
};

此时,赋给num的值应该是1314,因为它在结构声明中紧跟在name成员之后。新值1314取代了之前的520。

  • 在定义了结构体变量后,系统会为之分配内存单元。
  • student1 在内存中所占的的字节为 4+1+4+1+4=14.

二、在声明类型的同事定义变量

struct 结构体名
{
  成员列表;
}变量名列表;

成员列表的形式为 类型说明符 成员名;

举个例子2
struct student
{
    char *name;  // 学生名字
    int num;     // 学生学号
    int age;     // 学生年龄
}student1,student2;

此处省略了结构体名。虽然更简洁了,但是因为没有了名字,后面就不能用该结构定义新的变量。这个结构体的变量只能是student1和student2

三、typedef给结构体起别名

这种方法在实际操作中用的非常多,在嵌入式开发中几乎全都是用typedef给结构体起别名方法。比如你常见的STM32单片机中的程序,就是这样写的。

 typedef struct 结构体名
{
  成员列表;
}变量名列表;
举个例子3
// 给结构体模板struct student重新命名为student
typedef struct student
{
    char *name;  // 学生名字
    int num;     // 学生学号
    int age;     // 学生年龄
}student;

使用student创建三个结构体变量student1,student2, student3

student  student1 , student2 ,  student3

此处使用typedef为结构体模板struct student定义一个别名student,关于typedef的介绍移步至。进行查看。使用typedef给结构体创建一个别名,这在实际编程用使用非常广泛,如STM32单片机固件库中,使用得很多。

访问结构体成员

结构体成员的访问需要借助结构体成员运算符——点(.)。如:

student student1;             // 定义一个结构体变量student1
student1.name = "Liuyao"; // 给student1的成员name赋值
student1.num = 520;         // 给student1的成员num赋值
student1.age = 23;            // 给student1的成员age赋值

实例1

#include <stdio.h>
typedef struct student
{
 char *name;  // 学生名字
 int num;     // 学生学号
 int age;     // 学生年龄
}student;

int main(void)
{
 student student1;  // 定义一个结构体变量student1
 
 /* 给结构体变量stu1的成员进行赋值 */
 student1.name = "Liuyao";
 student1.num = 520;
 student1.age = 23;
 
 printf("\n============================================\n");
 printf("My name is %s\n", student1.name);
 printf("My num is %d\n", student1.num);
 printf("My age is %d\n", student1.age);
 printf("欢迎关注果果小师弟学习笔记!\n");
 printf("============================================\n");

 return 0;
}

实例2

#define KEY_FIFO_SIZE	10
typedef struct
{
	uint8_t Buf[KEY_FIFO_SIZE];		/* 键值缓冲区 */
	uint8_t Read;					/* 缓冲区读指针1 */
	uint8_t Write;					/* 缓冲区写指针 */
	uint8_t Read2;					/* 缓冲区读指针2 */
}KEY_FIFO_T;

//此处使用typedef为结构体模板struct 定义一个别名KEY_FIFO_T
static KEY_FIFO_T s_tKey; //定义一个结构体变量 s_tKey
void bsp_PutKey(uint8_t _KeyCode)
{
	s_tKey.Buf[s_tKey.Write] = _KeyCode;
	if (++s_tKey.Write  >= KEY_FIFO_SIZE)
	{
		s_tKey.Write = 0;
	}
}
static void bsp_InitKeyVar(void)
{
    uint8_t i;
    s_tKey.Read = 0;
    s_tKey.Write = 0;
    s_tKey.Read2 = 0;

}

例子三

#define GPIO_PORT_K1    GPIOI  //K1 键 
#define GPIO_PIN_K1	    GPIO_Pin_8

#define GPIO_PORT_K2    GPIOC //K2 键
#define GPIO_PIN_K2	    GPIO_Pin_13

#define GPIO_PORT_K3    GPIOH  //K2 键
#define GPIO_PIN_K3	    GPIO_Pin_4

#define GPIO_PORT_K4    GPIOG //摇杆UP键
#define GPIO_PIN_K4	    GPIO_Pin_2

#define GPIO_PORT_K5    GPIOF  //摇杆DOWN键
#define GPIO_PIN_K5	    GPIO_Pin_10

#define GPIO_PORT_K6    GPIOG  //摇杆LEFT键
#define GPIO_PIN_K6	    GPIO_Pin_3

#define GPIO_PORT_K7    GPIOG  //摇杆RIGHT键
#define GPIO_PIN_K7	    GPIO_Pin_7

#define GPIO_PORT_K8    GPIOI  //摇杆OK键
#define GPIO_PIN_K8	    GPIO_Pin_11

typedef struct
{

    uint32_t GPIO_Pin;    
    GPIOMode_TypeDef GPIO_Mode;
    GPIOSpeed_TypeDef GPIO_Speed;
    GPIOOType_TypeDef GPIO_OType;                                  
    GPIOPuPd_TypeDef GPIO_PuPd;
 
 }GPIO_InitTypeDef;
 
 static void bsp_InitKeyHard(void)//配置8个按键的GPIO口,为推挽模式
{
	GPIO_InitTypeDef      GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_ALL_KEY, ENABLE);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;	
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K1;
	GPIO_Init(GPIO_PORT_K1, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K2;
	GPIO_Init(GPIO_PORT_K2, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K3;
	GPIO_Init(GPIO_PORT_K3, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K4;
	GPIO_Init(GPIO_PORT_K4, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K5;
	GPIO_Init(GPIO_PORT_K5, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K6;
	GPIO_Init(GPIO_PORT_K6, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K7;
	GPIO_Init(GPIO_PORT_K7, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K8;
	GPIO_Init(GPIO_PORT_K8, &GPIO_InitStructure);
} 

这个例子是很清楚 。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

果果小师弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值