3.1 枚举
3.1.1 枚举
常量付哈化
- 用符号而不是具体的数字来表示程序中的数字;
枚举
- 用枚举而不是定义独立的const int变量;
- 枚举是一种用户定义的数据类型,用关键字enum以如下语法来声明:
enum 枚举类型名字{名字0,...,名字n};
- 枚举类型名字通常并不真的使用,要用的是在大括号里的名字,因为它们就像是常量符号,它们的类型是int,值则依次是从0到n。如:
enum colors{red,yellow,green};
- 就创建了三个常量,red的值是0,yellow的值是1,而green是2。
- 当需要一些可以排列起来的常量值时,定义枚举的意义就是给了这些常量值名字;
- 枚举量可以作为值;
- 枚举可以跟上enum作为类型;
- 但是实际上是以整数来做内部计算和外部输入输出的;
- 声明枚举量时可以指定值
enum COLOR{RED=1,YELLOW,GREEN=5};
即使给枚举类型的变量赋不存在的整数值也没有任何waring或error;
- 虽然枚举类型可以当作类型使用,但是实际上很少用;
- 如果有意义上排比的名字,用枚举比const int方便;
- 枚举比宏(macro)好,因为枚举有int类型。
3.2 结构
3.2.1 结构类型
声明结构类型
=#include <stdio.h>
int main()
{
struct date{
int month;
int day;
int year;
};
struct date today;
today.month=07;
today.day=31;
today.year=2014;
printf("Today's date is %i-%i-%i.\n",
today.year,today.month,today.day);
return 0;
}
在函数内/外?
- 和本地变量一样,在函数内部声明的结构类型只能在函数内部使用;
- 所以通常在函数外部声明结构类型,这样就可以被多个函数使用
声明结构的形式
struct point{
int x;
int y;
};
p1和p2都是point,里面有x和y的值
struct{
int x;
int y;
}p1,p2;
p1和p2都是一种无名结构,里面有x和y
struct point{
int x;
int y;
}p1,p2;
p1和p2都是point,里面有x和y的值
第一种和第三种形式都声明了结构point,但是第二种形式没有声明point,只是定义了两个变量。
结构变量
struct data today;
today.month=06;
today.day=19;
today.year=2005;
结构的初始化
struct data today={07,31,2014};
struct data thinmonth={.month=7,.year=2014};//day这时为0
结构成员
- 结构和数组有点像;
- 数组用[]运算符和下标访问其成员;
- a[0]=10;
- 结构用.运算符和名字访问其成员;
- today.day;
结构运算
- 要访问整个结构,直接用结构变量的名字;
- 对于整个结构,可以做赋值、取地址,也可以传递给结构参数;
- p1=(struct point){5,10};//相当于p1.x=5;p1.y=10;
- p1=p2;//相当于p1.x=p2.x;p1.y=p2.y;
- 数组无法做这两种运算!
结构指针
- 和数组不同,结构变量的名字并不是结构变量的地址,必须使用&符号;
- struct data *pDate=&today;
3.2.2 结构与函数
结构作为函数参数,整个结构可以作为参数的值传入函数,这时候是在函数内新建一个结构变量,并复制调用者的结构的值,也可以返回一个结构,这与数组完全不同。
输入结构
- 没有直接的方式可以一次scanf一个结构;
- 如果打算写一个函数来读入结构
#include <stdio.h>
struct point{
int x;
int y;};
void getStruct(struct point);
void output(struct point);
void main(){
struct point y=(0,0);
getStruct(y);
output(y);}
void getStruct(struct point p){
scanf("%d",&p.x);
scanf("%d",&p.y);
printf("%d,%d",x,y);}
void output(struct point p){
printf("%d,%d",x,y);}
C语言在函数调用时是传值的,所以函数中的p与main中的y是不同的,在函数读入了p的数值后,没有任何东西回到main,所以y还是{0,0}。
解决方案
之前的方案是把一个结构传入了函数然后在函数中操作,但是没有返回回去,问题在于传入函数的是外面那个结构的克隆体,而不是指针,传入结构与传入数组不同,在这个输入函数中,完全可以创建一个临时的结构变量,然后把这个变量返回给调用者
#include <stdio.h>
struct point{
int x;
int y;};
struct point getStruct(void);
void output(struct point);
int main(int argc,char const *argv[]){
struct point y=(0,0);
getStruct(y);
output(y);}
struct point getStruct(void){
struct point p;
scanf("%d",&p.x);
scanf("%d",&p.y);
printf("%d,%d",p.x,p.y);
return p;}
void output(struct point p){
printf("%d,%d",x,y);}
l另一种解决方案是把结构指针作为参数
struct date{
int month;
int day;
int year;
}myday;
struct data *p=&myday;
(*p).month=12;
p->month=12;
用->表示指针所指的结构变量中的成员
#include <stdio.h>
struct point{
int x;
int y;};
struct point* getStruct(struct point*);
void output(struct point);
void print()
int main(int argc,char const *argv[]){
struct point y=(0,0);
getStruct(&y);
output(y);
output(*getStruct(&));
print(getStruct(&y));}
struct point* getStruct(struct point *p){
scanf("%d",&p->x);
scanf("%d",&p->y);
printf("%d,%d",p->x,p->y);
return p;}
void output(struct point p){
printf("%d,%d",x,y);}
void print(const struct point *p){
printf("%d,%d",p->x,p->y);
}
3.2.3 结构中的结构
结构数组
struct date dates[100];
struct date dates[]={
{4,5,2005},{2,4,2005}};
机构中的结构
struct dateAndTime{
struct date sdate;
struct time stime;
}
嵌套的结构
struct point{
int x;
int y;
};
struct rectangle{
struct point pt1;
struct point pt2;
};
如果有变量
struct rectangle r;
就可以有:
r.pt1.x、r.pt2.x、r.pt1.y、r.pt2.y
如果有变量定义
struct rectangle r,*rp;
rp=&r;
那么下面的四种形式是等价的:
r.pt1.x
rp->pt1.x
(r.pt1).x
(rp->pt1).x
但是没有rp->pt1->x(因为pt1不是指针)
结构中的结构的数组
#include <stdio.h>
struct point{
int x;
int y;
};
struct rectangle{
struct point pt1;
struct point pt2;
};
void printRect(struct rectangle r)
{
printf("<%d,%d>to<%d,%d>\n",r.p1.x,r.p1.y,r.p2.x,r.p2.y);
}
int main(int argc,char const,*argv[])
{
int i;
struct rectangle rects[]={{{1,2},{3,4}},{{5,6},{7,8}}};//2rectangles
for(i=0;i<2;i++) printRect(rests[i]);
}
3.3.1 类型定义
自定义数据类型(typedef)
- C语言提供了一个叫做typedef的功能来声明一个已有的数据类型的新名字。比如:
typedef int Length;//Length等价于int类型
使得Length成为int类型的别名。
- 这样Length就可以代替int出现在变量定义和参数声明的地方。
typedef char* String[10];//String是10个字符串的数组的类型
typedef struct node{
int data;
struct node *next;
}aNode;//用aNode代替struct node
3.3.2 联合
存储
- 所有的成员共享一个空间;
- 同一时间只有一个成员是有效的;
- union的大小是其最大的成员;
初始化
- 对第一个成员做初始化
代码如下
#include <stdio.h>
typedef union{
int i;
char ch[sizeof(int)];
}CHI;
int main(int argc,char const *argv[])
{
CHI chi;
int i;
chi.i=1234;
for(i=0;i<sizeof(int);i++){
printf("%02hhX",chi.ch[i]);
}
printf("\n");
return 0;
}
输出
FFD2040000//为什么老师给的结果是D2040000?不懂啊
小端机器低位在前
这是一个非常常见的用union的场合,通过这种方式得到一个整数内部的各个字节,可以用来在做文件操作时把一个整数以二进制写到一个文件里时用来做读写的媒介。