C语言细节 其他数据类型

一.联合(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.功能:

typedef1个高级数据特性,可以为某一类型自定义名称.使用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值的数组
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值