枚举类型
定义:将需要使用的枚举类型的量一一列举出来。
作用:使用户能够自己定义标识符表示变量的值。(类似宏定义中定义常量的作用,但枚举类型是批量的,整合的。且在代码中而非编译中执行的)
语法:
声明:enum 枚举类型名 {枚举常量表列};
例如:
enum Color {red,black,white};
则:
Color为枚举类型
red,black,white为枚举元素(枚举常量)
注:Color类型的变量的值只能是以上定义的3个值之一。
定义:enum 枚举类型名 变量名列表;
例如:
enum Weekday workday,week_end;
则:
Weekday为枚举类型名
workday,week_end为两个Weekday类型的变量。
枚举类型值:
1.枚举元素作为常量是有值的,编译时将自动按定义时的顺序对它们赋值为0,1,2,3...
2.当使用枚举元素进行值判断(等值、大于、小于)时,将按常量处理(故枚举元素也称枚举常量),使用枚举元素的值来进行判断。
如:enum Open_modes{input,output,append};
在效果上和:
#define input 0
#define output 1
#define append 2
相似。(注意!虽然效果相似,当他们的原理是完全不同的,前者在代码执行过程中声明和定义。后者作为宏定义在编译过程中被执行)
3.声明枚举类型时,可另行指定枚举元素的值。
如:enum weekday{sum=7,mon=1,tue,wed,thu,fri,sat};
则sum的值将为7,mon的值将为1,tue的值将自动被赋为2,wed的值将自动被赋为3....
枚举类型的运算:
枚举类型可进行简单的运算,当使用枚举元素进行运算时,将使用枚举元素的值进行运算。效果可类比常量的运算
如:
enum Brand{lavida,tiggo,skoda};
enum Brand brand;
brand=lavida;
if(brand==lavida) printf("lovely brand!");
if(lavida>skoda) printf("woops!");
for(brand=lavida;brand<=skoda;brand++) printf("%d",brand);
brand=2;
printf("%d",brand);
代码示例1:
#include <stdio.h>
#include <stdlib.h>
/*这个程序用来测试枚举类型的定义和应用*/
int main()
{
enum Color{red,black,white};
enum Brand{lavida,tiggo,skoda};
enum Color color;
enum Brand brand;
for(color=red;color<=white;color++)
{
for(brand=lavida;brand<=skoda;brand++)
{
if(!((color==red&&brand==tiggo)||(color==white&&brand==skoda)))
{
switch(color)
{
case red:
printf("红");
break;
case black:
printf("黑");
break;
case white:
printf("白");
break;
}
switch(brand)
{
case lavida:
printf("Lavida\n");
break;
case tiggo:
printf("Tiggo\n");
break;
case skoda:
printf("Skoda\n");
break;
}
}
}
}
return 0;
}
结果:
解析:
对枚举类型的小应用,可以看到这样的代码可读性和可维护性都高了不少。
代码示例2:
#include <stdio.h>
#include <stdlib.h>
/*这个程序用于测试枚举类型的应用*/
/*以下代码实现输入一点的坐标,计算其关于x轴、y轴、原点的对称点的坐标*/
enum SymmetricStyle{axisx,axisy,point};//关于x轴/y轴/原点对称的枚举类型
struct CPoint//声明点坐标结构体
{
double x;//横坐标
double y;//纵坐标
};
struct CPoint SymmetricStyle(struct CPoint p,enum SymmetricStyle style)
{
struct CPoint p1;
switch(style)
{
case axisx:
p1.x=p.x;
p1.y=-p.y;
break;
case axisy:
p1.x=-p.x;
p1.y=p.y;
break;
case point:
p1.x=-p.x;
p1.y=-p.y;
}
return p1;
}
int main()
{
struct CPoint p1={2,2},p;
p=SymmetricStyle(p1,axisx);
printf("p1关于x轴的对称点为:(%.2lf,%.2lf)\n",p.x,p.y);
p=SymmetricStyle(p1,axisy);
printf("p1关于y轴的对称点为:(%.2lf,%.2lf)\n",p.x,p.y);
p=SymmetricStyle(p1,point);
printf("p1关于原点的对称点为:(%.2lf,%.2lf)\n",p.x,p.y);
return 0;
}
结果:
解析:
如上,声明枚举类型后,枚举元素甚至可以用于switch语句
联合体(共用体)
定义:将多个变量作为联合体定义,所有变量共用内存空间
作用:适用于需要同一值以不同形式表示的情况。
语法:
声明:union联合体名 {联合体变量表列};
引用:与结构体相同
特性:
1.几个不同的变量共占同一段内存的结构,因此联合体也称为共用体
2.联合体提供了从不同角度看待,以及用不同方式使用同一段内存空间的手段
3.共用体中的变量在内存中占用的字节数不一定,但都从同一地址开始使用,几个变量互相覆盖。
代码示例:
#include <stdio.h>
#include <stdlib.h>
/*这个程序用于测试联合体及其应用*/
/*声明联合体*/
union un
{
int i;
short int si[2];
char c[4];
};
int main()
{
union un x;
x.c[0]='A';
x.c[1]='B';
x.c[2]='C';
x.c[3]='D';
printf("%c,%c,%c,%c\n",x.c[0],x.c[1],x.c[2],x.c[3]);
printf("%d,%d\n",x.si[0],x.si[1]);
printf("%d\n",x.i);
return 0;
}
结果:
解析:
1.可以看到,当为char数组赋值时,联合体中的int型数据和short int数组也同步得到了值,且他们的值就是A,B,C,D的值首尾拼接得到的。(17475=68*256+67。。1145258561=17475*256*256+16961)
注意:
以上例子中,联合体的三个变量占用的字节数相同,但这并不是绝对的,联合体中变量占用的字节数也可不同,如:
union data
{
int i;
char ch;
double d;
}a,b,c;
对于以上联合体,i占用4个字节,ch占用一个字节,d占用8个字节。则该联合体的内存结构如下:
则该联合体占用的总空间为8字节(取最大)。
结论:联合体成员共享内存空间,联合体占用的内存空间长度为内存空间最长的成员的内存空间长度。
代码示例:
#include <stdio.h>
#include <stdlib.h>
/*这个程序用来测试联合体的应用*/
/*使用联合体实现4段式IP地址与串式IP地址的转换*/
union IP
{
unsigned char part[4];
unsigned int address;
};
void copyIp(union IP *a,int n[])
{
int i;
for(i=0;i<4;i++)
a->part[i]=n[i];
return;
}
int main()
{
union IP ip1,ip2;
int nums[4]={202,194,116,97};
copyIp(&ip1,nums);
printf("ip1:%d.%d.%d.%d\n",ip1.part[0],ip1.part[1],ip1.part[2],ip1.part[3]);
printf("ip1:%d\n",ip1.address);
ip2.address=234567;
printf("ip2:%d.%d.%d.%d\n",ip2.part[0],ip2.part[1],ip2.part[2],ip2.part[3]);
printf("ip2:%d\n",ip2.address);
if(ip1.address==ip2.address)
printf("same ip.\n");
else
printf("not same ip.\n");
return 0;
}
结果:
解析:以上为联合体的一种应用方式
自定义类型
定义:为已有的类型创建一个新的类型名称
语法:typedef 已有的类型名称 新类型名称;
示例:
typedef int INTEGER;
INTEGER i,j;//等价于int i,j;
typedef float REAL;
REAL a,b;//等价于float a,b;
注: typedef相当于为类型上了一层包装,使得可以通过新定义的名称来使用原有的类型。在实际编程中,最常将其运用于结构体的包装,如:
typedef struct date
{
int month;
int day;
int year;
}DATE;
像如上形式定义的结构体,调用起来就十分方便简洁了。如:
DATE birthday;
birthday.month=5;
birthday.day=10;
birthday.year=1995;
typedef作为一种包装工具,可用其来提高代码可读性。也可用其简化结构体等的使用。但其本身并无特殊的用法。因此不做代码示例。