结构体和其他数据类型

12.20本周总结

结构和其他数据类型

建立结构声明

结构声明描述了一个结构的组织布局。声明类似如下;

struct book{	
	char title[MAXTITL];
	char author[MAXAUTL];
	float value;
	};

该声明描述了一个由字符数组和一个float类型变量组成的结构。该变量只描述了该对象由什么组成。首先是关键字struct,它表明跟在其后的是一个结构,后面是一个可选的标记,稍后可在程序中使用该标记引用结构。所以,我们在后面的程序中可以这样声明:
struct book library;
这把library声明为一个 使用book结构布局的结构变量。
在结构声明中,用一对花括号括起来的是结构成员列表。每个成员都用自己的声明来描述。例如,title部分是一个内含MAXTITL个元素的char类型数组。成员可以是任意一种C的数据类型,甚至可以是其他 结构! 右花括号后面的分号是声明所必需的,表示结构布局定义结束。

定义结构变量

程序中创建 结构变量的一行是:
struct book 1 ibrary;
编译器执行这行代码便创建了一个结构变量library.编译器使用book模板为该变量分配空间:一 个内含MAXTITL个元素的char数组、一个内含MAXAUTL个元素的char数组和一个float类型的变量。 这些存储空间都与一个名称library结合在一起。
在结构变量的声明中,struct book 所起的作用相当于一般声明中的int或float。例如,可以定义两个struct book 类型的变量,或者甚至是指向struct book 类型结构的指针:
struct book doyle, panshin, * ptbook;
从本质上看,book结构声明创建了一个名为, book的新类型。
就计算机而言,下面的声明:
struct book library;
是以下声明的简化:

struct book {
char title [MAXTITL] ;
char author [AXAUTL] ;
float value;
} library;  /* 声明的右右花括号后跟变量名*/

换言之,声明结构的过程和定义结构变量的过程可以组合成一个步骤。 如下所示,组合后的结构商时 和结构变量定义不需要使用结构标记:

struct { /*无结构标记*/
char title [MAXTITL] ;
char author [MAXAUTL] ;
float value;
} library;

然而,如果打算多次使用结构模板,就要使用带标记的形式:或者,使用本章后面介绍的typedef.

初始化结构
struct book library = {
"The Pious Pirate and the Devious Damsel",
"Renee Vivotte" ,
1.95
};

我们在使用一对花括号中括起来的初始化列表进行初始化,各初始化项用逗号分隔。因此,title成员可以被初始化为一个字符串,value成员可以被初始化为一个数字。

访问结构成

结构类似于一个“ 超级数组”, 这个超级数组中,可以是一个元素为char 类型,下一个元素为forat 型,下一个元素为int数组。可以通过数组下标单独访问数组中的各元素,使用结构成员运算符一点( . )访问结构中的成员。例如,library . value即访问library的value 部分。可以像使用任何float类型变量那样使用library.value.与此类似可以像使用字符数组那样 使用library.title。
本质上,.title、 .author和.value 的作用相当于book结构的下标。
注意: &library. float正好符合要求。. 比&的优先级高,因此这个表达式和& (library. float)-样。

结构的初始化器

只初始化book结构的value成员,可以这样做:
struct book surprise = { .value = 10.99};
可以按照任意顺序使用指定初始化器:

struct book gift = { .value = 25.99,
author = "James Broadfool" ,
title = "Rue for the Toad"} ;

与数组类似,在指定初始化器后面的普通初始化器,为指定成员后面的成员提供初始值。另外,对特 定成员的最后一次赋值才是它实际获得的值。例如,考虑下面的代码:

struct book gift = { .value = 18.90.author = "James Broadfool"0.25 ;

赋给value的值最后是0.25。

声明结构数组
struct book library [MAXBKS];

以上代码把1bray声明为一个内含MAXBERS个元索的数组。数组的每个元素都是个数组。因此,1ibrary[0]是第1个book类型的结构变量,1ibrary[1]是第2个book类型的结构体 以此类推。数组名library 本身不是结构名,它是一个数组名, 该数组中的每个元素都是struct book类型的结构变量。

标识结构数组的成员
最后,总结一下:  1 ibrary //一个book结构的数组
1 ibrary[2 ]//一个数组元素,该元素是book结构
1 ibrary[2] . title//一个char数组( library[2]的title成员)
library[2] .title[4]//数组中library[2]元素的title成员的一个字符
结构指针

结构指针即指向结构的指针,为什么要使用结构指针,主要有一下三点原因:
①就像指向数组的指针比数组不本身更容易操作(例如在一个排序问题中)一样,指向结构的指针通常比结构本身更容易操作
②在一些早期的C实现中,结构不能作为参数被传递给函数,但指向结构的指针可以
③许多奇妙的数据表示都使用了不包含指向其他结构的指针的结构
介绍一个运算符(“->”),称为“间接成员运算符”
这个运算符与指向结构或联合的指针一起使用,用来指明结构或联合的成员。假设ptstru是一个指向结构的指针,member是由该结构模板指定的一个变量的成员,那么:ptstru ->member 就表示指向的结构的成员
声明和初始化结构指针
声明很简单,例如:
struct student *p
结构指针的初始化
结构指针本质是指针,既然是指针,那么传入的就应该是地址,所以初始化应该如下:
p = &stu //stu以struct student 为模板

向函数传递结构的信息

方法一:用结构体变量作实参
方法二:用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参

接下来分别举例解释这几种方法:我们首先定义一个student结构体如下:

struct student{ 
	int num; 	
	char name[20]; 	
	float score[3];
	 };

用结构体变量的成员作实参
这里写了一段代码来实现结构体的打印的功能,在print函数中传入了整个结构体变量。

#include<stdio.h> struct student{
 	int num;
 	char name[20]; 	
 	float score[3]; };//定义结构体 
 	struct student stu = { 	.num = 1702, 	
 	.name = "Linden", 	
 	.score = {99.7,99.2,98.9}
 	 };//结构体变量初始化 
 	 void print(struct student);//声明print函数 
 	 void main() { 	
 	 print(stu);//使用整个结构体变量作实参 }//主函数 
 	 void print(struct student stu) { 	
 	 printf("%d\n",stu.num); 	
 	 printf("%s\n",stu.name); 	
 	 printf("%.2f\n",stu.score[0]); 	
 	 printf("%.2f\n",stu.score[1]); 	
 	 printf("%.2f\n",stu.score[2]); }//print函数,注意
 	 struct student为变量类型,stu为形参

结果:
1702
Linden
99.70
99.20
98.90

联合声明

联合声明成员共享存储空间,而且在联合中同一时间内只能有一个成员。联合的长度取决于它最长成员的长度。
联合(union)外表与结构相似。但在内存布局上存在关键性的区别。在结构中每个成员依次存储,而在联合中,所有的成员都从偏移地址0开始存储。在某一时刻,只有一个成员真正存储于该位置。

类似于结构,联合的声明形式为:

union 结构标签(可选)
{
类型1 标识符1;
类型2 标识符2;
...
}

联合变量被初始化时,初始值必须是联合的第一个成员的类型,且必须位于一对花括号里,例如:

union
{
int a;
float b;
...
}x = {5};

把x.a初始化为5。不能把x初始化为一个浮点值。

enum和typedef
emum

开头不写Mon=1的话,Mon的默认值为0,然后从0开始增长。例如:

enum color {red,blue,green,yellow};

如果这样定义的话,red的值为0,blue的值为1,然后一次增长。

如果从中间开始赋值的话:

enum color {red,blue,green=5,yellow};

那么red到blue是按照默认的从0开始增长的,green就是定义的值5,然后green之后的值都是从5开始增长的。

typedef

1.常规变量类型定义
例如:typedef unsigned char uchar
描述:uchar等价于unsigned char类型定义
uchar c声明等于unsigned char c声明

2.数组类型定义
例如: typedef int array[2];
描述: array等价于 int [2]定义;
array a声明等价于int a[2]声明

扩展: typedef int array[M][N];
描述: array等价于 int [M][N]定义;
array a声明等价于int a[M][N]声明

3.指针类型定义
例如: typedef int *pointer;
描述: pointer等价于 int *定义;
pointer p声明等价于int *a声明

例如: typedef int *pointer[M];
描述: pointer等价于 int *[M]定义;
pointer p声明等价于int *a[M]声明明

4.函数地址说明
描述:C把函数名字当做函数的首地址来对待,我们可以使用最简单的方法得到函数地址
例如: 函数:int func(void);
unsigned long funcAddr=(unsigned long)func;
funcAddr的值是func函数的首地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值