C语言中的结构体、结构体指针

 1. 结构体的定义、引用、初始化

         有时候需要将不同类型的数据组合为一个整体,以便于引用。例如,一名学生有学号、姓名、性别、年龄、地址等属性,如果针对学生的学号、姓名、年龄等都单独定义一个变量,那么在有多名学生时,变量就难以分清。为此,C 语言提供结构体来管理不同类型的数据组合

#include <stdio.h>
#include <stdlib.h>
struct student
{
	int num;//num是结构体成员
	char name[20];
	char sex;
	int age;
	float score;
	char addr[30];
	//结构体类型声明,注意最后一定要加分号
};
int main()
{
	struct student s = { 1001, "lele",'M',20, 85.4, "Shenzhen" };//定义及初始化
	printf("%d %s %c %d %f %s\n", s.num, s.name,s.sex, s.age, s.score, s.addr);
}

 运行结果如下所示:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
struct student
{
	int num;//num是结构体成员
	char name[20];
	char sex;
	int age;
	float score;
	char addr[30];
	//结构体类型声明,注意最后一定要加分号
};
int main()
{
	struct student s = { 1001, "lele",'M',20, 85.4, "Shenzhen" };//定义及初始化
	struct student sarr[3];//定义一个结构体数组 sarr是结构体数组的数组名
	int i;
	printf("%d %s %c %d %f %s\n", s.num, s.name,s.sex, s.age, s.score, s.addr);
	for (i=0;i<3;i++)
	{
		scanf("%d%s %c%d%f%s", &sarr[i].num, sarr[i].name, &sarr[i].sex, &sarr[i].age, &sarr[i].score, sarr[i].addr);
		//要注意用scanf()连续输入时,%c前面要加一个空格
		// .是成员访问运算符   s.num是一个变量即可以赋值
		//sarr[i].name前面不加取地址符&是因为sarr[i].name整体是一个字符数组,里面存的是字符数组的起始地址,故不用加&。 sarr[i].addr同理
	}
	for (i = 0; i < 3; i++)
	{
		printf("%d %s %c %d %f %s\n", sarr[i].num, sarr[i].name, sarr[i].sex, sarr[i].age, sarr[i].score, sarr[i].addr);
	}
	system("pause");
	return 0; 
}
;

运行结果如下:

        结构体类型声明要放在 main 函数之前,这样 main 函数中才可以使用这个结构体,工作中往往把结构体声明放在头文件中。注意,结构体类型声明最后一定要加分号,否则会编译不通。另外,定义结构体变量时,使用 struct student 来定义,不能只有 struct或 student,否则也会编译不通,sarr 是结构体数组变量。结构体的初始化只能在一开始定义,如果 struct student  s={1001,"lele",M,20,85.4,"Shenzhen已经执行,即 struct    student   s 已经定义,就不能再执行s=(1001,"lele",M,20,85.4,Shenzhen"。如果结构体变量已经定义,那么只能对它的每个成员单独赋值,如 s.num=1003.
        采用“结构体变量名.成员名”的形式来访问结构体成员,例如用 s.num 访问学号。在进行打印输出时,必须访问到成员,而且 printf 中的%类型要与各成员匹配。使用 scanf 读取标准输入时,也必须是各成员取地址,然后进行存储,不可以写成&s,即不可以直接对结构体变量取地址,整型数据 (%d)、浮点型数据 (%f)、字符串型数据 (%s)都会忽略空格,但是字符型数据 (%c) 不会忽略空格,所以如果要读取字符型数据,那么就要在待读取的字符数据与其他数据之间加入空格。

2.结构体指针

          一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以设置一个指针变量,用它指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。

#include <stdio.h>
#include <stdlib.h>
//结构体指针
struct student
{
	int num;//num是结构体成员
	char name[20];
	char sex;
	//结构体类型声明,注意最后一定要加分号
};
int main()
{
	struct student s = { 1001, "wangle",'M' };//定义及初始化
	struct student *p;//定义一个结构体指针
	p = &s;//取地址
	printf("%d %s %c\n", (*p).num, (*p).name, (*p).sex);
	return 0;
}

运行结果如下:

需要注意的是:

        因为我们的目的是想要通过结构体指针输出结构体成员信息,p是一个结构体指针,里面存储的是结构体变量s的起始地址,*p表示拿到了这个结构体变量,然后*p.num再取成员,但是这样为什么错了?其实涉及到运算符的优先级问题,*的优先级要低于.的优先级,所以要把*p加上一对小括号变成(*p).num才可以。

此外,除了用.外,还可以使用->

这两种写法都需要掌握。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//结构体指针
struct student
{
	int num;//num是结构体成员
	char name[20];
	char sex;
	//结构体类型声明,注意最后一定要加分号
};
int main()
{
	struct student s = { 1001, "wangle",'M' };//定义及初始化
	struct student* p;//定义一个结构体指针
	p = &s;//取地址
	printf("%d %s %c\n", (*p).num, (*p).name, (*p).sex);
	printf("%d %s %c\n", p->num,p->name,p->sex);


	//结构体的初始化
	struct student sarr[3] = { 1001, "lilei", 'M', 1005, "zhangsan", 'M', 1007, "lili", 'F' };
	int num;
	p = sarr;//数组名
	printf("-----------------------------\n");
	num = p->num++;//num=p->num;p->num++
	//第一步直接把++去掉:num=p->num
	//第二步看运算符的优先级,->的优先级高于++,故把 p->num看做一个整体是1001,然后这个整体加加是1002
	printf("num=%d,p->num=%d\n", num, p->num);//1001,1002
	num = p++->num;//num=p->num;p++;
	//第一步直接把++去掉:num=p->num  num现在是1002
	//第二步 ++的运算规则的从右到左的且是单目的  故肯定是对p加加,即p++:p刚开始是指向1001这个结构体的,加加后指向1005这个结构体
	printf("num=%d,p->num=%d\n", num,p->num);//1002,1005
	return 0;
}

运行结果如下所示:

3.typedef 使用

         前面定义结构体变量时使用的语句是 struct student s,以这种方式来定义结构体变量有些麻烦,即每次都需要写 struct student。那么有没有简单一些的定义方式呢?答案是肯定的,可以选择使用 typedef 声明新的类型名来代替已有的类型名。

typedef 的作用就是起别名!

使用stu定义结构体变量和使用struct student 定义结构体变量是等价的,使用INTEGER定义变量i和使用int定义变量i是等价的;pstu 等价于 struct student*,所以p是结构体指针变量。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//给结构体类型起别名,叫stu
//起了结构体指针类型的别名,叫pstu
typedef struct student {
	int num;
	char name[20];
	char sex;
}stu, * pstu;

typedef int INTEGER;//为什么要对 int起别名,为了代码即注释  非重点
int main()
{
	stu s = { 1001,"wangle",'M' };
	pstu p;//stu* p1,那么p1也是一个结构体指针 这两种方式都可以声明一个结构体指针
	INTEGER i = 10;
	p = &s;//p是一个结构体指针 取地址s
	printf("i=%d,p->num=%d\n", i, p->num);
	return 0;
}

运行结果如下:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值