1.枚举
enum name_of_value{name0,name1,...namen};
枚举是一种定义出来的数据类型,使用关键字enum
进行声明。枚举类型的名字name_of_value
通常并不是真正地去使用,要使用的是在大括号的中的名字name
。他们就相当于常量符号,数据类型是int
,值则依次从0对应到n。注意这个定义相当于一个语句了,后面要加;
。实际上就是赋予一堆常量值名字。
enum name_list{Long,Ding,King,Liu};
#include <stdio.h>
enum color {red,yellow,bule};//定义一个枚举类型:enum color
void f(enum color varlue);//提前声明
int main()
{
enum color var1 = bule;//注意enum color 属于一种数据类型,类似int,float...
//定义的枚举类型中的量可以作为值
printf("var1的值是%d\n", var1);//enum color类型实际上是以整形int来做内部计算和外部输入和输出的
f(var1);
return 0;
}
void f(enum color varlue)//要求传入的变量是enum color类型
{
printf("使用f函数打印:%d", varlue);
}
在枚举结构的最后加上一个常量名字number,具有计数的功能,它可以作为数组的下标。
这样,RED为1,YELLOW为2,GREEN为5。
使用枚举的主要需求是需要定义排比的符号量,而不必去写一大竖行。
2.1结构类型
日期有年、月、日;时间有时、分、秒;一个人的信息有姓名、性别、学号等
结构格式:声明结构 + 定义变量
struct name_of_data
{
int var1;
int var2;
...
};//声明结构
struct date today;//定义变量
//可理解为定义类一种struct date的数据类型
声明了一个叫做date
的结构类型,大括号里面是结构的成员变量,里面的格式就是正常定义变量的写法,注意要在大括号外边加上;
因为这属于一个完整的语句。后边的struct date today;
为定义了一个struct date
类型的变量today
,但是没有完全初始化。
第三种写法是简写,第二种写法没有定义结构的名字
关于结构变量的初始化的方式
#include <stdio.h>
struct date
{
int year;
int month;
int day;
};
int main()
{
//第一种 先定义随后赋值
struct date today;//变量today的结构类型为 struct date
today.day = 1;
today.month = 1;
today.year = 2001;
//第二种 按照顺序写在大括号里一一对应,直接赋值
struct date today = {1,1,2001};
//第三种 精确赋值,注意成员变量之前要加"."
struct date today = {.day = 1,.month = 1};
//没有赋值的成员变量默认为0
//另外还可以定义不同的变量
struct date today1 = {1,1,2001};
struct date today2 = {2,1,2001};
.......
}
使用大括号的方式 类似数组,就像第三种没有提到的year,那么自动赋值为0。
结构和数组类似,数组中有单元,结构中有成员;
但是数组中单元的数据类型必须相同,结构中的成员变量的结构类型可以不同;
关于访问元素:
要分清结构类型struct date
和结构变量today
、student
,结构类型只是一个框架,每一个结构变量里面都有自己的结构成员。
访问的时候today.year
,注意在.
左边的是结构变量而不是结构类型,结构类型是虚的,结构变量是实的。.
是用来访问结构变量中的成员的。
数组在初始化完成之后就不可改变了,属于被const;结构类型可以通过大括号前面强制类型转换赋值给结构变量,并且结构变量之间可以赋值运算,而数组是无法做到的。
可以看到,两个结构变量today和today2实际上是两个完全独立的变量。另外初始化变量的时候:struct date today = {01,01,2001};
是可以的;但是语句分开的时候必须使用(struct date)
强制转换类型 :struct date today; today = (struct date){01,01,2001};
声明结构指针:struct date *p_day = &day;
(在这里day是已经初始化了的) 也就是数据类型 + 指针名字。就像普通指针的定义方式那样,int *p;
表示指针p是指向一个结构类型的指针。
2.2结构与函数
结构变量是可以在函数中传来传去的。
scanf函数可以读入结构变量.结构成员scanf("%d",&today.day);
- 对于第二点:
结构变量y的输出结果将仍会是0
将一个结构变量作为参数传入一个函数后,在函数中实际上是对copy变量的操作,对函数外面的结构变量没有任何影响,也就是所谓的C语言的传值方式。
解决方案: -
让函数返回结构变量
函数甚至可以返回一个struct date
类型的结构变量
因为如果传递一个structure的copy既费空间又费时间。传递指针的话更加轻便。
注意取地址运算符&
的优先级低于访问成员变量运算符.
,所以不用加括号写:&(today.day)
;结构变量和数组不同,本身不表达地址,需要加上&
都可以传递给指针:
struct date* p = &today;
int* q = &today.month;//注意指向的类型
因为优先级原因,使用*p.month = 12;
会报错,得加括号(*p).month = 12;
;
它的简写形式:p->month = 12;
“p所指的那个结构变量的month”属于一个运算符->
其实在定义函数的时候,想要返回什么值就返回什么值,返回结构指针struct date* F(){}
;返回结构变量struct date F(){}
;返回整形int F(){}
;返回整形指针int* F(){}
…唯一的区别就是以前函数返回的类型是int,float,double
那些类型,只不过现在函数返回的类型是自己定义的结构类型。
2.2结构的嵌套操作
定义出一个数据类型结构后,我们就可以初始化一个结构变量,甚至是一个结构数组…
struct time Times[3] = {{1,5,4},{1,5,2},{4,5,7}};
相当于
struct time Times[3];
Times[0] = (struct time){ 1,5,4 };
Times[1] = (struct time) { 1,5,2 };
Times[2] = (struct time){ 4,5,7 };
比如说通过两个点来确定一个矩形:
//结构的声明:
struct point
{
int x;
int y;
};
struct rectangle
{
struct point p1;
struct point p2;
};
//定义变量、完成嵌套:
int main()
{
struct point p1 = {1,5};
struct point p2 = {4,6};
struct rectangle r = {struct point p1,struct point p2};
//访问嵌套结构:
int i = r.p1.x;
int o = r.p1.y;
int l = r.p2.x;
int j = r.p2.y;
//还是说访问的时候在.左边的是结构的名字,而不是定义的的数据类型
}
其中
{ {1,2},{3,4} }
是rects[0];{ {5,6},{7,8} }
是rects[1]。rects[0]和rects[1]都是一个嵌套结构。