结构与联合_C语言快速入门与计算机二级备考
结构
声明结构体类型
-
结构体:本质是用户自己建立的,由不同类型数据组成的,组合类型的数据结构
-
一般形式为:
structt 结构名 {成员列表(类型名 成员名;)};例如:struct Student{ int num; char name[20]; char sex; int age; float score; char pho[30]; };//这里有分号! -
结构体中的成员可以属于另一个结构体类型,嵌套使用,例如:
struct date{int y; int m; int d;}; struct Student{……struct date birthday;}//在Student内使用date的结构体类型 -
和本地变量一样,在函数内部声明的结构类型只能在函数内部使用,而在外部声明的结构类型可以被多个函数使用
定义结构体变量
-
定义结构体变量
struct 结构类型名 结构体变量名;struct point{ int x; int y; }//定义了point,包含x和y struct point p1,p2;//定义了point类型的p1,p2 //声明结构时能够同时完成声明与定义结构变量,用于只需要几个结构体变量的情况,如下 struct { int x; int y; } p1,p2; //p1与p2都是一种无名结构,里面包含了x和y struct point{ int x; int y; }p1,p2; //p1与p2都是point,里面有x和y -
为变量赋值
结构体变量名.类型名=变量;例如:
struct Student a;//定义学生a结构体变量 a.name="lihua"; a.age=18; a.birthday.mouth=10; struct Student a={“lihua”,18,10……};//必须按顺序,编译器自动对号入座 struct Student a={.age=18, .birthday.mouth=10……}; //可以只给部分值,类似于数组的初始化,没给的值将会被赋0 struct Student b; a=b;//同结构体变量可以直接赋值 -
.是一个取成员的运算符,类似数组的[]数组用[]和下标访问其中成员,如
a[0]=10;结构用.和名字访问其中成员,如
a.x=10;
结构体变量的运算
- 对于整个结构,可以直接用结构变量的名字,赋值、取地址、传递参数等
-
p1=(struct point){5,10}; //强制类型转换,将5和10两个值转换为struct point类型的变量 //相当于p1.x=5;p1.y=10; p1=p2;//相当于p1.x=p2.x;p1.y=p2.y //数组就无法做这两种运算
函数与结构
-
结构能传入函数/被函数返回
从函数的((20241111170228-47u8xd5 "参数传递"))中得知,C在调用函数时,只能传递值给函数,变量与参数并不会有联系,结构类型同理(注意区分结构与数组的不同,结构并非指针)
在作为函数参数时,被传入函数的并非外面的结构,而只是外面结构的克隆体,在不同函数内对其进行的操作将无法对原本的结构形成修改
//设计一个输入结构的函数来说明 struct a { int x; int y; }; void input(struct a p){ scanf("%d", &p.x); scanf("%d", &p.y); //`.`取成员的优先级比`&`取地址高,所以`&a.x`表示取a.x的地址 printf("%d,%d\n", p.x, p.y); } int main(){ struct a test = { 0,0 }; input(test); printf("%d,%d", test.x, test.y); return 0; } //input函数中的p与main函数中的test没有关系,因为函数只能传递值而非量 //因此,程序实际做的事是:将一个结构传入函数,在这个函数内对其修改,而没有返回回去 //因此,两次输出并不会相同,表明这个函数无法对结构变量test修改 //解决方法:利用结构变量可以直接赋值的特性,在函数中创立一个临时的结构变量,再将其返回 struct a input() { struct a p; scanf("%d", &p.x); scanf("%d", &p.y); printf("%d,%d\n", p.x, p.y); return p;//创建了一个临时的结构变量p作为替身,对其修改后返回 } int main() { struct a test = { 0,0 }; test=input();//将修改后返回的p赋给test printf("%d,%d", test.x, test.y); return 0; } -
指向结构的指针
与上面的例子相比,使用指针要比创建整个结构的替身这种做法更方便,更省空间
用
->运算符表示指针所指的结构变量中的成员,例如:struct date { int month; int day; int year; }myday; struct date *p=&myday;//结构与数组不同,它不是指针,所以要用上&取地址 //p这个指针指向myday这个结构变量 (*p).month=12; //.运算符取出p所指的myday中的month //()强制类型转换将12变成date类型中的month p->month=12;//这样与上述代码效果相同 //->运算符优先级高于对取出元素的运算由此可以对上文的结构输入程序进行修改:
void main(){ struct a test={0,0}; input(&test);//将要修改的结构test的地址传入 printf("%d,%d", test.x, test.y); }//由于通过指针直接操作外面的test,所以不需要将p返回 void input(struct a *p){ scanf("%d",&(p->x)); scanf("%d",&(p->y)); }
结构的变体
-
结构数组
为了方便定义多个结构体变量,使用结构数组
结构数组可以同结构变量一样被赋值,被传递给一个函数
有了结构数组,多个结构输入程序可以简化流程,不必一个一个结构成员输入
struct date dates[100];//这就定义了一个结构数组 //这表示一个数组dates,含有100元素 //每个元素都是结构体变量struct date,都包含所有的结构体成员 -
结构中的结构
在声明结构体变量时提到了结构体中嵌套使用结构体
对于含嵌套的结构体,使用指针例:
struct point{ int x; int y; };//声明一个结构point struct rectangle{ struct point pt1; struct point pt2; };//声明了一个嵌套了point结构的结构rectangle //包含关系为:{rectangle类型 [point类型 pt1(int x,y)][point类型 pt2(int x,y)]} struct rectangle r; r.pt1.x//对于rectangle类型的r,可以用这种方式取被嵌套的成员 struct rectangle r,*rp; rp=&r;//声明了两个结构体变量,一个是r,另一个是指向r的指针 r.pt1.x rp->pt1.x (r.pt1).x (rp->pt1).x//这四种形式等价 rp->pt1->x//这种写法是错误的,因为pt1是指针
联合
声明联合
-
union 联合名 {成员列表(类型名 成员名;)};类似于结构
struct,也由不同的成员构成,例如:union AnElt{ int i; char c; } elt1,elt2; //同创建结构类型一样,此处创建了两个名为elt1与elt2的联合类型AnElt
联合的特点
-
与结构的区别在于结构的各个成员是相互独立的,但联合中的各个成员共用一个内存空间,同一时间内只有一个成员是有效的
但是在使用时不能直接引用,要同结构体一样引用其中的成员
-
联合的大小是一个联合最大的成员
-
对于这些特点的解释:一个联合占据一定的内存空间,其中成员共同使用这些空间,当另一个成员使用时将会盖住原来成员的数据,而这些成员都无法超出联合的大小
联合的应用
-
初始化时,对联合的第一个成员初始化
-
利用
union输出一个变量在内存中保存的各个字节typedef union{ int i; char ch[sizeof(int)]; }CHI;//创建一个联合并命名为CHI,其中包括一个整数i与一个长度为整数类型大小的字符数组 int main() { CHI test; test.i=1234;//以1234为例,其16进制为00 00 04 D2 for(int i=0;i<sizeof(int);i++) { printf("%02hhX",test.ch[i]); } return 0; } //注意:我们常用的x86计算机属于小端储存(数据的高字节保存在内存的高地址中) //例如:0x12345678在内存中分布为0x78|0x56|0x34|0x12(设从左到右内存地址升高) //于是1234实际保存的方式为D2 04 00 00,这较小的一位会保存在前面(低位在前)
自定义数据类型
-
例如:在使用结构体变量时,每次都要写
struct 变量名以表示其类型,又或者使用无符号数据类型时类型名会很长,书写很不方便 -
通过
typedef可以声明一个已有数据类型的新名字 -
这种做法可以改善程序的可读性,或者简化了复杂的变量名例如:
typedef int length;//使length成为int类型的别名,可替代int出现在变量定义或参数声明中 typedef struct ADate{ …… }Date;//定义了一个结构体变量类型struct ADate,简化其名为Date length = 1000;//重载了已有的类型名,新名字的含义更清晰 Date d ={……};//简化了原本复杂的变量名struct ADate d
本文来自博客园,作者:无术师,转载请注明原文链接:https://www.cnblogs.com/artlessist/p/18547832
本文使用知识共享4.0协议许可 CC BY-NC-SA 4.0
特别说明版权归属的文章以及不归属于本人的转载内容(如引用的文章与图片)除外
浙公网安备 33010602011771号