c语言中结构体链表,C语言中的结构体,联合,链表和枚举,位域(下)

一、联合的定义

定义一个联合类型的一般形式为:

union 联合名

{

成员表

};

成员表中含有若干成员,成员的一般形式为: 类型说明符 成员名 成员名的命名应符合标识符的规定。

例如:

union

perdata { int class; char office[10]; };

定义了一个名为perdata的联合类型,它含有两个成员,一个为整型,成员名为class;另一个为字符数组,数组名为office。联合定义之后,即可进行联合变量说明,被说明为perdata类型的变量,可以存放整型量class或存放字符数组office。

二、联合变量的说明

联合变量的说明和结构变量的说明方式相同,

也有三种形式。即先定义,再说明;定义同时说明和直接说明。以perdata类型为例,说明如下:

union

perdata { int class; char officae[10]; }; union perdata

a,b; 或者可同时说明为: union perdata { int class;

char office[10]; }a,b;或直接说明为: union { int class; char office[10];

}a,b 经说明后的a,b变量均为perdata类型。 它们的内存分配示意图如图7—8所示。a,b变量的长度应等于 perdata

的成员中最长的长度, 即等于

office数组的长度,共10个字节。从图中可见,a,b变量如赋予整型值时,只使用了2个字节,而赋予字符数组时,可用10个字节。

联合变量的赋值和使用

对联合变量的赋值,使用都只能是对变量的成员进行。 联合变量的成员表示为: 联合变量名.成员名

例如,a被说明为perdata类型的变量之后,可使用 a.class a.office 不允许只用联合变量名作赋值或其它操作。

也不允许对联合变量作初始化赋值,赋值只能在程序中进行。还要再强调说明的是,一个联合变量,

每次只能赋予一个成员值。换句话说,一个联合变量的值就是联合变员的某一个成员值。

[例7.15]设有一个教师与学生通用的表格,教师数据有姓名,年龄,职业,教研室四项。学生有姓名,年龄,职业,班级四项。

编程输入人员数据, 再以表格输出。

main()

{ struct { char name[10]; int age; char job; union { int class;

char office[10]; } depa; }body[2]; int n,i; for(i=0;i<2;i++) {

printf("input name,age,job and department\n"); scanf("%s %d

%c",body[i].name,&body[i].age,&body[i].job);

if(body[i].job=='s') scanf("%d",&body[i].depa.class); else

scanf("%s",body[i].depa.office); } printf("name\tage job

class/office\n"); for(i=0;i<2;i++) { if(body[i].job=='s')

printf("%s\t= < %d\n",body[i].name,body[i].age

,body[i].job,body[i].depa.class); else printf("%s\t= <

%s\n",body[i].name,body[i].age, body[i].job,body[i].depa.office); }

} 本例程序用一个结构数组body来存放人员数据, 该结构共有四个成员。其中成员项depa是一个联合类型,

这个联合又由两个成员组成,一个为整型量class,一个为字符数组office。在程序的第一个for语句中,输入人员的各项数据,先输入结构的前三个成员name,age和job,然后判别job成员项,如为"s"则对联合depa·class输入(对学生赋班级编号)否则对depa·office输入(对教师赋教研组名)。

在用scanf语句输入时要注意,凡为数组类型的成员,无论是结构成员还是联合成员,在该项前不能再加"&"运算符。如程序第18行中

body[i].name是一个数组类型,第22行中的body[i].depa.office也是数组类型,因此在这两项之间不能加"&"运算符。程序中的第二个for语句用于输出各成员项的值:

本章小结

1.

结构和联合是两种构造类型数据,是用户定义新数据类型的重要手段。结构和联合有很多的相似之处,它们都由成员组成。成员可以具有不同的数据类型。成员的表示方法相同。都可用三种方式作变量说明。

2.

在结构中,各成员都占有自己的内存空间,它们是同时存在的。一个结构变量的总长度等于所有成员长度之和。在联合中,所有成员不能同时占用它的内存空间,它们不能同时存在。联合变量的长度等于最长的成员的长度。

3. “.”是成员运算符,可用它表示成员项,成员还可用“->”运算符来表示。

4.

结构变量可以作为函数参数,函数也可返回指向结构的指针变量。而联合变量不能作为函数参数,函数也不能返回指向联合的指针变量。但可以使用指向联合变量的指针,也可使用联合数组。

5. 结构定义允许嵌套,结构中也可用联合作为成员,形成结构和联合的嵌套。

6. 链表是一种重要的数据结构,它便于实现动态的存储分配。本章介绍是单向链表,还可组成双向链表,循环链表等。

typedef是类型定义的意思。typedef

struct 是为了使用这个结构体方便。

具体区别在于:

若struct node {}这样来定义结构体的话。在申请node 的变量时,需要这样写,struct node n;

若用typedef,可以这样写,typedef struct node{}NODE; 。在申请变量时就可以这样写,NODE

n;

区别就在于使用时,是否可以省去struct这个关键字。

分三块来讲述:

1 首先:

在C中定义一个结构体类型要用typedef:

typedef struct Student

{

int a;

}Stu;

于是在声明变量的时候就可:Stu stu1;

如果没有typedef就必须用struct Student stu1;来声明

这里的Stu实际上就是struct Student的别名。

另外这里也可以不写Student(于是也不能struct Student stu1;了)

typedef struct

{

int a;

}Stu;

但在c++里很简单,直接

struct Student

{

int a;

};

于是就定义了结构体类型Student,声明变量时直接Student stu2;

===========================================

2其次:

在c++中如果用typedef的话,又会造成区别:

struct Student

{

int a;

}stu1;//stu1是一个变量

typedef struct Student2

{

int a;

}stu2;//stu2是一个结构体类型

使用时可以直接访问stu1.a

但是stu2则必须先 stu2 s2;

然后 s2.a=10;

===========================================

3 掌握上面两条就可以了,不过最后我们探讨个没多大关系的问题

如果在c程序中我们写:

typedef struct

{

int num;

int age;

}aaa,bbb,ccc;

这算什么呢?

我个人观察编译器(VC6)的理解,这相当于

typedef struct

{

int num;

int age;

}aaa;

typedef aaa bbb;

typedef aaa ccc;

也就是说aaa,bbb,ccc三者都是结构体类型。声明变量时用任何一个都可以,在c++中也是如此。但是你要注意的是这个在c++中如果写掉了typedef关键字,那么aaa,bbb,ccc将是截然不同的三个对象。

第四篇:C/C++中typedef

struct和struct的用法

struct

_x1 { ...}x1; 和 typedef struct _x2{ ...} x2; 有什么不同?

其实,

前者是定义了类_x1和_x1的对象实例x1, 后者是定义了类_x2和_x2的类别名x2 ,

所以它们在使用过程中是有取别的.请看实例1.

[知识点]

结构也是一种数据类型,

可以使用结构变量, 因此, 象其它 类型的变量一样, 在使用结构变量时要先对其定义。

定义结构变量的一般格式为:

struct

结构名

{

类型

变量名;

类型

变量名;

...

}

结构变量;

结构名是结构的标识符不是变量名。

另一种常用格式为:

typedef

struct 结构名

{

类型

变量名;

类型

变量名;

...

}

结构别名;

另外注意:

在C中,struct不能包含函数。在C++中,对struct进行了扩展,可以包含函数。

======================================================================

实例1:

struct.cpp

#include

using namespace std; typedef struct _point{ int x; int y; }point;

//定义类,给类一个别名 struct _hello{ int x,y; } hello; //同时定义类和对象 int main()

{ point pt1; pt1.x = 2; pt1.y = 5; cout<< "ptpt1.x=" <<

pt1.x << "pt.y=" < //hello pt2; //pt2.x = 8; //pt2.y =10;

//cout<

//上面的hello pt2;这一行编译将不能通过. 为什么? //因为hello是被定义了的对象实例了. //正确做法如下:

用hello.x和hello.y hello.x = 8; hello.y = 10; cout<<

"hellohello.x=" << hello.x << "hello.y=" < return 0;

} 第五篇:问答

Q:

用struct和typedef struct 定义一个结构体有什么区别?为什么会有两种方式呢?

struct

Student

{

int a;

} stu;

typedef struct Student2

{

int a;

}stu2;

A:

事实上,这个东西是从C语言中遗留过来的,typedef可以定义新的复合类型或给现有类型起一个别名,在C语言中,如果你使用

struct xxx

{

}; 的方法,使用时就必须用 struct xxx var 来声明变量,而使用

typedef struct

{

}的方法 就可以写为 xxx var;

不过在C++中已经没有这回事了,无论你用哪一种写法都可以使用第二种方式声明变量,这个应该算是C语言的糟粕。

用法小结

第一、四个用途

用途一:

定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如:

char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,

// 和一个字符变量;

以下则可行:

typedef char* PCHAR; // 一般用大写

PCHAR pa, pb; // 可行,同时声明了两个指向字符变量的指针

虽然:

char *pa, *pb;

也可行,但相对来说没有用typedef的形式直观,尤其在需要大量指针的地方,typedef的方式更省事。

用途二:

用在旧的C的代码中(具体多旧没有查),帮助struct。以前的代码中,声明struct新对象时,必须要带上struct,即形式为:

struct 结构名 对象名,如:

struct tagPOINT1

{

int x;

int y;

};

struct tagPOINT1 p1;

而在C++中,则可以直接写:结构名

对象名,即:

tagPOINT1 p1;

估计某人觉得经常多写一个struct太麻烦了,于是就发明了:

typedef struct tagPOINT

{

int x;

int y;

}POINT;

POINT

p1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候

或许,在C++中,typedef的这种用途二不是很大,但是理解了它,对掌握以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代码。

枚举

在实际问题中, 有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有七天,一年只有十二个月,

一个班每周有六门课程等等。如果把这些量说明为整型, 字符型或其它类型显然是不妥当的。

为此,C语言提供了一种称为“枚举”的类型。在“枚举”类型的定义中列举出所有可能的取值,

被说明为该“枚举”类型的变量取值不能超过定义的范围。应该说明的是, 枚举类型是一种基本数据类型,而不是一种构造类型,

因为它不能再分解为任何基本类型。

枚举类型的定义和枚举变量的说明

一、枚举的定义枚举类型定义的一般形式为:

enum 枚举名

{ 枚举值表 };

在枚举值表中应罗列出所有可用值。这些值也称为枚举元素。

例如: enum weekday

{ sun,mou,tue,wed,thu,fri,sat };

该枚举名为weekday,枚举值共有7个,即一周中的七天。 凡被说明为weekday类型变量的取值只能是七天中的某一天。

二、枚举变量的说明 如同结构和联合一样,枚举变量也可用不同的方式说明,

即先定义后说明,同时定义说明或直接说明。设有变量a,b,c被说明为上述的weekday,可采用下述任一种方式:

enum weekday

{

......

};

enum weekday a,b,c;或者为: enum weekday

{

......

}a,b,c;或者为: enum

{

......

}a,b,c;

枚举类型变量的赋值和使用

枚举类型在使用中有以下规定:

1. 枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。例如对枚举weekday的元素再作以下赋值:

sun=5;mon=2;sun=mon; 都是错误的。

2. 枚举元素本身由系统定义了一个表示序号的数值,从0 开始顺序定义为0,1,2…。如在weekday中,sun值为0,mon值为1,

…,sat值为6。

main(){

enum weekday { sun,mon,tue,wed,thu,fri,sat } a,b,c; a=sun; b=mon;

c=tue; printf("%d,%d,%d",a,b,c); } 3.

只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量。如: a=sum;b=mon; 是正确的。而: a=0;b=1;

是错误的。如一定要把数值赋予枚举变量,则必须用强制类型转换,如: a=(enum

weekday)2;其意义是将顺序号为2的枚举元素赋予枚举变量a,相当于: a=tue;

还应该说明的是枚举元素不是字符常量也不是字符串常量, 使用时不要加单、双引号。

main(){

enum body { a,b,c,d } month[31],j; int i; j=a;

for(i=1;i<=30;i++){ month[i]=j; j++; if (j>d) j=a; }

for(i=1;i<=30;i++){ switch(month[i]) { case a:printf(" -

%c\t",i,'a'); break; case b:printf(" - %c\t",i,'b'); break; case

c:printf(" - %c\t",i,'c'); break; case d:printf(" - %c\t",i,'d');

break; default:break; } } printf("\n"); }位域

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态,

用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,

并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。

这样就可以把几个不同的对象用一个字节的二进制位域来表示。一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:

struct 位域结构名

{ 位域列表 };

其中位域列表的形式为: 类型说明符 位域名:位域长度

例如:

struct

bs { int a:8; int b:2; int c:6; }; 位域变量的说明与结构变量说明的方式相同。

可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如:

struct

bs { int a:8; int b:2; int c:6; }data;

说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。对于位域的定义尚有以下几点说明:

1.

一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:

struct

bs { unsigned a:4 unsigned :0 unsigned

b:4 unsigned c:4 }

在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。

2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。

3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:

struct

k { int a:1 int :2 int b:3 int c:2 };

从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配的。

二、位域的使用位域的使用和结构成员的使用相同,其一般形式为:

位域变量名·位域名 位域允许用各种格式输出。

main(){

struct bs { unsigned a:1; unsigned b:3; unsigned c:4; } bit,*pbit;

bit.a=1; bit.b=7; bit.c=15; printf("%d,%d,%d\n",bit.a,bit.b,bit.c);

pbit=&bit; pbit->a=0; pbit->b&=3;

pbit->c|=1;

printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c); }

上例程序中定义了位域结构bs,三个位域为a,b,c。说明了bs类型的变量bit和指向bs类型的指针变量pbit。这表示位域也是可以使用指针的。

程序的9、10、11三行分别给三个位域赋值。(

应注意赋值不能超过该位域的允许范围)程序第12行以整型量格式输出三个域的内容。第13行把位域变量bit的地址送给指针变量pbit。第14行用指针方式给位域a重新赋值,赋为0。第15行使用了复合的位运算符"&=",

该行相当于:

pbit->b=pbit->b&3位域b中原有值为7,与3作按位与运算的结果为3(111&011=011,十进制值为3)。同样,程序第16行中使用了复合位运算"|=",

相当于: pbit->c=pbit->c|1其结果为15。程序第17行用指针方式输出了这三个域的值。

类型定义符typedef

C语言不仅提供了丰富的数据类型,而且还允许由用户自己定义类型说明符,也就是说允许由用户为数据类型取“别名”。

类型定义符typedef即可用来完成此功能。例如,有整型量a,b,其说明如下: int aa,b;

其中int是整型变量的类型说明符。int的完整写法为integer,

为了增加程序的可读性,可把整型说明符用typedef定义为: typedef int INTEGER

这以后就可用INTEGER来代替int作整型变量的类型说明了。 例如: INTEGER a,b;它等效于: int a,b;

用typedef定义数组、指针、结构等类型将带来很大的方便,不仅使程序书写简单而且使意义更为明确,因而增强了可读性。例如:

typedef char NAME[20]; 表示NAME是字符数组类型,数组长度为20。

然后可用NAME 说明变量,如: NAME a1,a2,s1,s2;完全等效于: char

a1[20],a2[20],s1[20],s2[20]

又如:

typedef struct stu{ char name[20];

int age;

char sex;

} STU;

定义STU表示stu的结构类型,然后可用STU来说明结构变量: STU body1,body2;

typedef定义的一般形式为: typedef 原类型名 新类型名 其中原类型名中含有定义部分,新类型名一般用大写表示,

便于区别。在有时也可用宏定义来代替typedef的功能,但是宏定义是由预处理完成的,而typedef则是在编译时完成的,后者更为灵活方便。

本章小结

1. 枚举是一种基本数据类型。枚举变量的取值是有限的,枚举元素是常量,不是变量。

2.

枚举变量通常由赋值语句赋值,而不由动态输入赋值。枚举元素虽可由系统或用户定义一个顺序值,但枚举元素和整数并不相同,它们属于不同的类型。因此,也不能用printf语句来输出元素值(可输出顺序值)。

3. 位运算是C语言的一种特殊运算功能,

它是以二进制位为单位进行运算的。位运算符只有逻辑运算和移位运算两类。位运算符可以与赋值符一起组成复合赋值符。如&=,|=,^=,>>=,<<=等。

4. 利用位运算可以完成汇编语言的某些功能,如置位,位清零,移位等。还可进行数据的压缩存储和并行运算。

5. 位域在本质上也是结构类型,不过它的成员按二进制位分配内存。其定义、说明及使用的方式都与结构相同。

6. 位域提供了一种手段,使得可在高级语言中实现数据的压缩,节省了存储空间,同时也提高了程序的效率。

7. 类型定义typedef

向用户提供了一种自定义类型说明符的手段,照顾了用户编程使用词汇的习惯,又增加了程序的可读性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值