- 共用体
1.1共用体的概念 :使几个不同的变量共占同一段内存的结构,称为“共用体”类型的结构。
1.2 定义共用体类型变量的一般形式为:
union 共用体名
{
成员表列
}变量表列;
其实定义共用体变量有3中方法,其方法与定义结构体变量的3种方法类似:
1) 先声明共用体类型再定义变量名
union date
{
int year;
int month;
long day;
};
union date d1, d2;
2)在定义结构体类型的同时定义变量
union 共用体名
{
成员列表
}变量名列表;
例:
union date
{
int year;
int month;
long day;
}d1, d2;
3) 直接定义共用体类型变量
union
{
成员列表
}变量名列表;
例:
union
{
int year;
int month;
long day;
}d1, d2;
1.3 共用体与结构体的比较
结构体变量所占内存长度是各成员占的内存长度之和,因为每个成员分别占有其自己的内存单元。共用体变量所占的内存长度等于最长的成员的长度,因为所用成员共享一个公共的内存单元,所以需要满足最长成员的长度。见例1.
例如 : 上面定义的“共用体”变量d1、d2各占8个字节(因为在GCC中一个整型变量占4个字节,一个长整形变量占8个字节),而不是各占 4 +4+8=16个字节。
1.4 共用体变量的引用方式
只有先定义了共用体变量才能引用它,而且不能引用共用体变量,而只能引用共用体变量中的成员。
例如 : 前面定义了d1, d2为共用体变量
d1.year (引用共用体变量d1中的整型变量year)
d1.month(引用共用体变量d1中的字符变量month )
d1.day(引用共用体变量d1中的长整型变量day)
1.5 共用体类型数据的特点
1)同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一种,而不是同时存放几种。
2)共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员就失去作用。
3)共用体变量的地址和它的各成员的地址都是同一地址。
(这3条特点共同说明了,所用共用体成员共享一个公共的内存单元)见例1.
4)不能对共用体变量名赋值,也不能企图引用变量名来得到一个值,又不能在定义共用体变量时对它初始化。
5)不能把共用体变量作为函数参数,也不能使函数带回共用体变量,但可以使用指向共用体变量的指针。
6)共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型定义中,数组也可以作为共用体的成员。见例2.
//例1.
/#include<stdio.h>union date
{
int year;
int month;
long day;
}d1, d2;void main()
{
d1.year = 2018;
d1.month = 01;
d1.day = 01;printf("%d-%d-%ld\n", d1.year, d1.month, d1.day);
printf("&d1.year: %o, &d1.month: %o, &d1.day: %o\n", &d1.year, &d1.month, &d1.day);
printf("sizeof(d1): %d\n", sizeof(d1));d1.year = 2018;
d1.month = 01;
d1.day = 02;printf("%d-%d-%ld\n", d1.year, d1.month, d1.day);
printf("&d2.year: %o, &d2.month: %o, &d2.day: %o\n", &d2.year, &d2.month, &d2.day);
printf("sizeof(union date): %d\n", sizeof(union date));
}
//输出:
1-1-1
&d1.year: 30010100, &d1.month: 30010100, &d1.day: 30010100
sizeof(d1): 82-2-2
&d2.year: 30010110, &d2.month: 30010110, &d2.day: 30010110
sizeof(union date): 8
//例2
/#include <stdio.h>struct
{
int num;
char name[10];
char sex;
char job;
union
{
int banji;
char position[10];
}category;
}person[2]; //为了方便先假设一个学生一个老师。void main()
{
int i;
for(i=0; i < 2; i++)
{
printf("Please input the num: ");
scanf("%d", &person[i].num);
printf("Please input the name: ");
scanf("%s", person[i].name);
fflush(stdin);
printf("Please input the sex(M/F): ");
scanf("%c", &person[i].sex);
fflush(stdin);
printf("Please input the job(s/t): ");
scanf("%c", &person[i].job);
fflush(stdin);
if( person[i].job == 's' )
{
printf("Please input the class: ");
scanf("%d", &person[i].category.banji);
fflush(stdin);
}
else if( person[i].job == 't' )
{
printf("Please input the position: ");
scanf("%s", person[i].category.position);
fflush(stdin);
}
else
{
printf("Input Error!!\n");
}
printf("\n");
}
printf("No. name sex job class/position\n");
for( i=0; i < 2; i++ )
{
if( person[i].job == 's')
{
printf("%-6d%-10s%-3c%-3c%10d\n", person[i].num,
person[i].name, person[i].sex, person[i].job,
person[i].category.banji);
}
else
{
printf("%-6d%-10s%-3c%-3c%10s\n", person[i].num,
person[i].name, person[i].sex, person[i].job,
person[i].category.position);
}
}
}
- 枚举类型
2.1 概念:在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有七天,一年只有十二个月,一个班每周有六门课程等等。如果把这些量说明为整型,字符型或其它类型显然是不妥当的。为此,C语言提供了一种称为“枚举”的类型。
2.2 枚举变量的声明:设有变量 a,b,c 被说明为上述的 weekday ,可采
用下述任一种方式:
1)enum weekday{ sun,mou,tue,wed,thu,fri,sat };
enum weekday a, b, c;
2)enum weekday{ sun,mou,tue,wed,thu,fri,sat }a, b, c;
3)enum { sun,mou,tue,wed,thu,fri,sat }a, b, c;
2.3 注意事项:
1)在“枚举”类型的定义中列举出所有可能的取值,被说明为该“枚举”类型的变量取值不能超过定义的范围。
2)枚举类型是一种基本数据类型,而不是一种构造类型,因为它不能再分解为任何基本类型。
3)在枚举值表中应罗列出所有可用值。这些值也称为枚举元素。
4)在C编译中,对枚举元素按常量处理,故称枚举常量。它们不是变量,不能对它们赋值。
5)枚举元素作为常量,它们是有值的,C语言编译按定义时的顺序使它们的值为0,1,2...
6)枚举值可以用来作判断比较。
7)一个整数不能直接赋给一个枚举变量。
//例3
/#include <stdio.h>void main()
{
enum weekday{sun, mon, tue, wed, thu, fri, sat}a, b, c; /定义枚举类型weekday,并声明枚举变量a, b, c/
a = 1; // a = 1;这样是不行的,因为这里是用一个整形的1来覆盖a所代表的 enum
b = mon;
c = sat;
printf("%d, %d, %d", a, b, c);
printf("\n\n");
}
//输出: 1, 1, 6
//例4
/#include <stdio.h>void main()
{
enum boy{Tom, Danny, Gan, LiLei}month[31], j;
int i;
j = Tom;
for( i=1; i <= 30; i++ )
{
month[i] = j;
j++;
if( j > LiLei )
{
j = Tom;
}
}
for( i=1; i <= 30; i++)
{
switch( month[i] )
{
case Tom: printf(" %4d %s\t", i, "Tom");
break;
case Danny: printf(" %4d %s\t", i, "Danny");
break;
case Gan: printf(" %4d %s\t", i, "Gan");
break;
case LiLei: printf(" %4d %s\t", i, "LiLei");
break;
default:
break;
}
}
printf("\n");
}
//输出:
1 Tom 2 Danny 3 Gan 4 LiLei 5 Tom
6 Danny 7 Gan 8 LiLei 9 Tom 10 Danny
11 Gan 12 LiLei 13 Tom 14 Danny 15 Gan
16 LiLei 17 Tom 18 Danny 19 Gan 20 LiLei
21 Tom 22 Danny 23 Gan 24 LiLei 25 Tom
26 Danny 27 Gan 28 LiLei 29 Tom 30 Danny
- typedef
3.1 typedef的作用:用 typedef 声明新的类型名来代替已有的类型名
3.2 用 typedef 定义类型
1)声明 INTEGER 为整型:“typedef int INTEGER;” 见例5
//例5
/#include <stdio.h>
typedef int INTEGER;void main()
{
INTEGER i = 1;
int j = 2;
printf("%d, %d\n", i, j);
}
//输出:1, 2
2)声明结构类型
Typedef struct
{
int month ;
int day ;
int year ;
}DATE;
//例6
/#include <stdio.h>
typedef struct
{
int month;
int day;
int year;
}DATE;
void main()
{
DATE date_one;
date_one.month = 12;
date_one.day = 31;
date_one.year = 2017;
printf("%d - %d - %d \n", date_one.year, date_one.month, date_one.day);
}
//输出: 2017-12-31
3)声明NUM为整型数组类型:“typedef int NUM[100];” 见例7.
//例7
/#include <stdio.h>typedef int NUM[100];
void main()
{
NUM num = {0};
printf("%d\n", sizeof(num));
}
//输出:400
4)声明STRING为字符指针类型:“typedef char* STRING ;”见例8.
//例8.
/#include <stdio.h>typedef char* P; //声明字符指针类型P
void main()
{
P p1;
p1 = "I love UNSW";
printf("%s\n", p1);
}
//输出: I love UNSW
5)声明P为函数指针类型:“typedef void (*P)();”见例9
//例9
/#include <stdio.h>typedef void (*P)(); //声明函数指针类型P
void fun();
void main()
{
P p1; // 这里的p1等价于“void (*p1)();”即定义p1为函数指针类型P的实参
p1 = fun; //将函数fun()的入口地址赋给指针变量p1
( * p1)(); //函数指针通过调用函数实现输出
}void fun()
{
printf("I love UNSW\n");
}
//输出:I love UNSW
3.3 用 typedef 定义类型的方法
1)按定义变量的方法写出定义体(如: int i )
2)将变量名换成新类型名(例如:将 i 换成 COUNT )。
3)在最前面加typedef (例如: typedef int COUNT )
4)然后可以用新类型名去定义变量(例如: COUNT i,j;)
3.2 关于typedef的说明
1)用 typedef 可以声明各种类型名,但不能用来定义变量。
2)用 typedef 只是对已经存在的类型增加一个类型名,而没有创造新的类型。
3)当不同源文件中用到同一类型数据时,常用 typedef 声明一些数据类型,把它们单独放在一个文件中,然后在需要用到它们的文件中用 #include命令把它们包含进来。
4)使用 typedef 有利于程序的通用与移植。
3.1 typedef 与 #define 的比较
相似:typedef 与 #define 有相似之处,例如: typedef int COUNT ; #define COUNT int 的作用都是用 COUNT 代表 int 。
区别:#define 是在预编译时处理的,它只能作简单的字符串替换,而 typedef 是在编译时处理的。实际上它并不是作简单的字符串替换,而是采用如同定义变量的方法那样来声明一个类型。
另外注意,“typedef (int * ) p1;”和“#define p2 int*” 一个有分号,一个没有分号
网友评论