一.联合(Union)
"联合"又称"共用体",是C中的1种数据类型,内在同一个内存空间中存储不同的数据类型(但不是
同时!!!).其典型用法是,设计1种表以存储无规律且事先不知道顺序的混合类型
1.联合的创建与赋值:
//创建1个联合模板:没有创建1个联合变量,而相当于创建了1个数据类型
union <uvar> {
<type> <name1>;
...
};
//创建1个联合变量/联合数组/联合指针:创建了1个联合变量
union <uvar> <var>;
union <uvar> <var>[<len>];
union <uvar> * <pvar>;
//1个联合变量可以存储不同类型的值(只要该类型在模板中存在),但同一时间只能存储1个值,也就只能存储1种类型的值
//编译器将按联合变量中需要空间最大的类型分配内存空间,以保证空间充足
//参数说明:
uvar:联合模板的名字
type:数据类型
//即该类型联合可以储存的所有类型
name:成员名
var:联合变量/联合数据的变量名
len:数组长度
pvar:指向联合变量的指针变量的指针名
//初始化联合变量:
union <uvar> <var>=<var2>;
union <uvar> <var>={<val>};
union <uvar> <var>={.<name>=<val>};
//法2只能初始化name1,而法3可以初始化任意指定的成员
//参数说明:
var2:另1个已赋值的同类型联合变量
val:指定联合变量的值
//赋值:
<var>.<name>=<val>;
//实例:
#include <stdio.h>
union hold {
int digit;
double bigfl;
char letter;
};
int main(void) {
union hold valA;
valA.letter='R';
union hold valB=valA;
union hold valC={88};
union hold valD={
.bigfl=118.2
};
valA.digit=12;
union hold aval[3]={
valA,valB,valC
};
union hold * pval=&valD;
printf("%d,%c,%d,%f\n",valA,valB,valC,valD);
printf("%d,%f",aval[0],*pval);
return 0;
}
//结果:
12,R,88,118.200000
12,118.200000//注意修改valA后,aval[0]也改变
2.使用联合变量:
对于1个已赋值的联合变量,直接使用即可,无需使用<var>.<name>的形式.实际上,这种情况下
<var>和<var>.<name>(<name>只要属于相应模板即可,无需与<var>当前存储的数据类型相
同)的作用都是相同的:
#include <stdio.h>
union hold {
int digit;
double bigfl;
char letter;
};
int main(void) {
union hold valA;
valA.letter='R';
printf("%c,%c,%c",valA.letter,valA.letter,valA.letter);
return 0;
}
//结果:
R,R,R
//#####################################################################
利用指针访问联合时使用->运算符:
<pvar>-><name>;
//实例:
#include <stdio.h>
union hold {
int digit;
double bigfl;
char letter;
};
int main(void) {
union hold v={20};;
union hold * p=&v;
int i=p->digit;//注意:这里必须使用类型合适的name
printf("%d",i);//20
return 0;
}
3.1个实例:
struct owner {
char socsecurity[12];
};
struct leasecompany {
char name[40];
};
union data {
struct owner owncar;
struct leasecompany leasecar;
};
struct cardata {
char make[15];
int status;
union data ownerinfo;
};
struct cardata info;
如果info.status==0,表示该车辆属于驾驶者,使用info.ownerinfo.ownercar存储驾驶者
的信息;如果info.status==1,则表示该车辆属于租赁公司,使用info.ownerinfo.ownercar
存储租赁公司的信息
4.匿名联合:
C11新增了匿名联合的特性,允许使用无名的联合:
union {
<type> <var>;
...
}
//实例:
#include <stdio.h>
struct s {
int i;
union {
char c;
double d;
};
};
int main(void) {
struct s s1={
12,{.c='A'}
};
printf("%c",s1.c);//结果:A
//如果把匿名联合放在其他联合(U)或结构体(S)中,匿名联合中的成员会被视为U/S中的直接成员
return 0;
}
二.共享名称空间
C使用"名称空间"(Namespace)标识程序中的各部分,即通过名称来标识.如作用域就是名称空间
这一概念的一部分.在特定的作用域中,结构体标记/联合标记/枚举标记(即模板的名称)共享同1
个名称空间,但该名称空间不与变量共享.故在同1个作用域中,标记名可与变量名相同而不会产生
冲突.但在同1个作用域中不允许重复的标记名/变量名
尽管如此,以2中方式使用相同的标识符可能造成混乱.另外,C++不允许这样做,因为其把变量名和
标记名放在相同的名称空间中
三.typedef
1.功能:
typedef是1个高级数据特性,可以为某一类型自定义名称.使用typedef的主要目的是创建1个方
便,易识别的类型名或简化复杂的数据类型;还能提高程序的可移植性,如size_t和time_t类型
注意:typedef不创建新类型,只是为已有的类型增加了1个标签
2.语法:
为类型自定义名称:typedef <type> <defname>;
利用自定义名称定义变量:<defname> <var>;
//作用域取决于typedef定义所在的位置,规则和普通变量相同
//参数说明:
type:数据类型
defname:自定义的名称
//遵循变量名的命名规则;通常使用全部大写的名称
var:变量名
//实例:
#include <stdio.h>
typedef unsigned int UI;
int main(void) {
UI ui=111;
printf("%u",ui);//结果:111
return 0;
}
3.typedef与#define:
typedef的功能与#define类似,二者功能存在部分重叠,如下面2行代码的功能相同:
#define BYTE unsigned char;
typedef unsigned char BYTE;
//#####################################################################
但二者有3点不同:
①#define创建的符号名可用于类型或值,而typedef创建的符号名只能用于类型
②typedef由编译器解释,而#define由预处理器解释
③在受限范围内,typedef比#define更灵活
如对于指针类型:
typedef char * STRING;
STRING name,sign;//相当于char * name,* sign
//name与sign都是指针,因为编译器把STRING解释成1个类型的标识符
#define STRING char *
STRING name,sign;//相当于char * name,sign
//即只有name是指针,因为预处理器用char *替换STRING
还可以将typedef用于结构体:
typedef struct complex {//模板名complex可省略
float real;
float imag;
} COMPLEX;
四.一些复杂的声明
在复杂的变量声明中,常包含以下符号:
符号 | 含义 |
---|---|
* | 表示1个指针 |
() | 表示1个函数 |
[] | 表示1个数组 |
下面是一些示例:
int board[8][8];//1个包含8个子数组的数组,每个子数组包含8个int值
int **ptr;//1个指向指针的指针,被指向的指针指向int值
int * risks[10];//1个包含10个指针的数组,每个元素都是指向int的指针
int (* risks)[10];//1个指向数组的指针,数组中包含10个int值
int * oof[3][4];//1个3×4的数组,每个元素都是指向int的指针
int (* uuf)[3][4];//1个指向3×4数组的指针,数组中包含3×4个int值
int (* uof[3])[4];//1个包含3个指针的数组,指针都指向1个包含4个int值的数组
int * fump(int);//1个函数,返回int*,参数为int
int (* frump)(int);//1个指向函数的指针,该函数的参数/返回值均为int
int (* frump[3])(int);//1个包含3个指针的数组,指针都指向参数/返回值均为int的函数
关于优先级:
①(...) > ...[] = ...() > *
//...[]表示数组名后的[];...()表示函数名后的()
②同级之间,从左往右结合
//#####################################################################
使用typedef:
typedef int arr5[5];//包含5个int值的数组
typedef arr5 * parr5;//指向数组的指针,数组中包含5个int值
typedef parr5 arrp10[10];//包含10个指针的数组,指针都指向包含5个int值的数组