C语言---结构体,共用体,枚举,typedef声明

C语言结构体

结构体定义:C语言允许用户允许自己建立由不同类型数据组成的组合型的数据结构。

结构体类型的定义

结构体类型定义的一般形式如下:

struct 结构体名
{
    数据类型 成员1;
    数据类型 成员2;
    数据类型 成员3;
    ...
};

其中,struct是关键字,是结构体类型的标志。

关于结构体定义的注意点:

结构体的成员名可以与程序中其他定义为基本类型的变量名重名,不会出现冲突;
结构体定义最后是以分号结束的,不要遗漏;
如果结构体类型定义在函数内部,则这个类型名的作用域仅为该函数;如果是定义在所有函数的外部,则可在整个程序中使用

结构体变量的定义

结构体变量定义一共有三种方式,下面将逐个介绍。
1 先声明结构体类型,再定义结构体变量。比如:

struct 结构体名 结构体变量名列表;

2 声明结构体类型的同时定义结构体变量。比如:

struct 结构体名
{
    数据类型 成员1;
    数据类型 成员2;
    数据类型 成员3;
    ...
}结构体变量名列表;

3 直接定义结构体变量,即省略结构体名。比如:

struct
{
    数据类型 成员1;
    数据类型 成员2;
    数据类型 成员3;
    ...
}结构体变量名列表;

在定义了结构体变量之后,系统将为其分配内存单元。每个结构体变量所占用内存大小为各个成员项所占用的内存大小之和

结构体类型和结构体变量的区别:

结构体类型是一种数据类型,系统不为其分配存储空间;
结构体变量是实在的变量,系统为其分配存储空间,可以进行赋值、存取或运算

结构体变量的初始化

在定义结构体变量的同时就对其成员赋初值的操作,就是对结构体变量的初始化。结构体变量的初始化方式与数组类似。在定义结构体变量的同时,把赋给每个成员的初始化用大括号括起来,各个数据之间以逗号隔开。具体形式如下:

struct 结构体名 结构体变量1={成员1初始化值,成员2初始化值...} , 结构体变量2={成员1初始化值,成员2初始化值...} ...;

或者

struct 结构体名
{
    数据类型 成员1;
    数据类型 成员2;
    数据类型 成员3;
    ...
}结构体变量1={成员1初始化值,成员2初始化值...} , 结构体变量2={成员1初始化值,成员2初始化值...} ...;

结构体变量的引用

结构体变量的引用分为结构体成员变量的引用和对结构体变量本身的引用。

结构体成员变量的引用

结构体变量包括一个或多个结构体成员变量,引用其成员变量的语法格式如下:

结构体变量名 . 成员名

其中,“.”是专门的结构体成员运算符,用于连接结构体变量名和成员名,属于最高级运算符。

C语言规定,同类型的结构体类型之间可以进行赋值运算,因此这样的赋值运算是允许的:

struct student stu1, stu2;
stu2 = stu1;

用sizeof运算符计算结构体变量所占用的内存空间。其一般使用形式如下:

sizeof(结构体变量名);
sizeof(结构体类型名);

用&运算符对结构体变量进行取址运算。

结构体指针

在C语言中可以定义结构体变量,也可以定义结构体类型的指针。当指针变量指向一个结构体变量时,就将这个指针变量称为结构体指针。此时,结构体指针变量的值就是它指向的结构体变量的首地址。

指向结构体变量的指针

和普通的指针变量定义类似,结构体指针的定义也使用*作为指针定义的运算符。其一般定义形式为:

struct 结构体类型名 *结构体指针变量名;

此时通过结构体指针变量来访问成员变量的一般形式如下:

结构体指针变量名 -> 成员名

C语言规定,*结构体指针变量名通过“->”访问成员名,在内存中都会被转化为(结构体指针变量名).成员名的方式访问。也就是说,以下三种对成员变量的访问效果是一致的:

结构体变量名 . 成员名
结构体指针变量名 -> 成员名
( *结构体指针变量名) . 成员名

指向结构体数组的指针

结构体指针也可以指向一个已经定义的结构体数组。结构体指针可以指向结构体数组的首地址,也可以指向结构体数组的某个元素的地址。可以通过结构体指针值的递增和递减改变其所指的元素。

指向结构体数组的结构体指针变量使用起来并不复杂,但是要注意区分以下情况:

假设p是指向一个结构体数组的指针变量,num为该结构体的某个成员,那么

p->num++            /* 等价于(p->num)++,先取成员值,对成员值++ */
++p->num            /* 等价于++(p->num),先对成员值++,再取成员值 */
(p++)->num            /* 先取成员值,再指针++ */
(++p)->num            /* 先指针++,再取成员值 */

应该注意的是,一个结构体指针变量虽然可以用来访问结构体变量或者结构体数组元素的成员,但是不能使它指向一个成员。也就是说,不允许取一个成员的地址来赋予它。比如:

p = &stu[0].sex;            /* 错误 */
p = stu;            /* 正确,赋予结构体指针变量数组的名称 */
p = &stu[0];            /* 正确,赋予结构体指针变量数组首元素的地址 */

例子:

#include <stdio.h>
 
int main()
{
	struct ucode
	{
		char u1;
		int u2;
	}tt[4] = { {'a',97},{'b',98},{'c',99},{'d',100} };
 
		struct ucode *p = tt;
 
		printf("%c %d\n", p->u1, p->u2);
		printf("%c\n", (p++)->u1);
		printf("%c %d\n", p->u1, p->u2++);
		printf("%d\n", p->u2);
		printf("%c %d\n", (++p)->u1, p->u2);
		p++;
		printf("%c %d\n", ++p->u1, p->u2);
 
	return 0;
}

这段程序的运行结果为:

a 97
a
b 98
99
c 99
e 100
请按任意键继续. . .

结构体与函数

作为函数参数
在函数之间直接传递结构体类型的数据属于传值调用方式;在函数之间直接传递结构体指针类型的数据属于传址调用方式。

作为函数返回值
C语言中,一个函数只能有一个返回值。但是如果函数确实需要带回多个返回值,可以利用全局变量解决,或者使用指针作为函数的参数解决。在学习了结构体之后,可以在被调函数中返回一个结构体类型的数据,而多个返回值都存放在这个结构体类型中。这样也是非常方便的。

C语言共用体

C语言除了提供结构体这种可包含多种类型数据的构造类型,还提供了一种从形式上看和结构体非常相似的构造类型——共用体。

在C语言中,可以定义不同数据类型的数据共用同一段内存空间,以满足某些特殊的数据处理要求,这种数据构造类型就是共用体。共用体又称联合体,和结构体类型一样,它也是由各种不同类型的数据组成的,这些数据称为共用体的成员。成员既可以拥有相同的数据类型,也可以拥有不同的数据类型。

不同的是,在共用体中,C语言编译系统使用了覆盖技术,使共用体的所有成员在内存中具有相同的首地址,共占用一段内存空间,这些数据可以相互覆盖,在不同的时间保存不同的数据类型和不同长度的成员的值。也就是说,在某一时刻,只有最新存储的数据是有效的。运用此种类型数据的优点是节省存储空间。

共用体的定义

共用体类型定义的一般形式如下:

union 结构体名
{
    数据类型 成员1;
    数据类型 成员2;
    数据类型 成员3;
    ...
};

其中:union是C语言中的关键字,表明是在进行一个共用体类型的定义

共用体变量的定义、初始化和引用

共用体变量的定义,和结构体变量的定义类似,定义共用体变量的方法也有三种:

union 共用体名
{
    数据类型 成员1;
    数据类型 成员2;
    数据类型 成员3;
    ...
}共用体 变量名列表;
union 共用体名 共用体变量名列表;
nuion 共用体名
{
    数据类型 成员1;
    数据类型 成员2;
    数据类型 成员3;
    ...
}共用体变量名列表;
union
{
    数据类型 成员1;
    数据类型 成员2;
    数据类型 成员3;
    ...
}共用体变量名列表;

当一个共用体变量被定义后,编译程序会自动给变量分配存储空间,其长度为共用体数据成员中所占内存空间最大的成员的长度

共用体变量的初始化,和结构体变量的初始化截然不同。由于共用体的成员共占用一个首地址,所以在任何时刻只能存放其中一个成员的值。所以,在对共用体变量进行定义并初始化时,只能对其中的第一个成员赋初值,即给其赋予一个和第一个成员类型相同的常量,初值需要用大括号括起来

也就是说,共用体变量初始化的时候只能给第一个成员赋初值,但是其他时候可以通过对共用体变量成员的引用来进行赋值。同时,不能直接引用共用体变量,只能引用变量中的成员,除非将一个共用体变量赋值给另一个同类型的共用体变量。比如:

union mark
{
    int score;
    char degree[4];
}liming={90};                /* 正确 */
liming=100;                /* 错误 */
liming.score=100;                /* 正确 */

C语言中结构体和共用体的区别

struct和union都是由多个不同的数据类型成员组成,但在任何同一时刻,union中只存放了一个被选中的成员,而struct的所有成员都存在;
在struct中,各成员都占有自己的内存空间,它们是同时存在的,一个struct变量的总长度等于所有成员长度之和。在Union中,所有成员不能同时占用它的内存空间,它们不能同时存在。Union变量的长度等于最长的成员的长度;
对于union的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于struct的不同成员赋值是互不影响的。

C语言枚举类型

在实际问题中,有些变量的取值被限定在一个有限的范围内。为此,C语言提供了一种称为“枚举”的类型,在枚举类型的定义中列举出所有的可能的取值,被说明为该枚举类型的变量取值不能超过定义的范围。

枚举类型定义的一般形式为:

enum 枚举名
{
    枚举值[=整型常量],
    枚举值[=整型常量],
    ...
    枚举值[=整型常量],
};

如果枚举枚举值没有初始化,也就是声明中[=整型常量]没有定义,则从第一个枚举值开始,顺序赋给标识符0,1,2,3,4……。但是当枚举中的某个成员赋值后,其后面的成员按顺序依次加1

枚举类型声明的时候,有几点需要注意:

枚举成员之间用逗号分隔,不是分号;
枚举成员初始化时可以赋予负数,但是依次加1的规律不变

枚举变量定义的方式和结构体、共用体类似:

enum 枚举名
{
    枚举值[=整型常量],
    枚举值[=整型常量],
    ...
    枚举值[=整型常量],
}枚举变量名列表;

枚举变量使用的时候,有几点需要注意:

枚举值是常量,不是变量,不能在程序中用赋值语句再对它进行赋值;
只能把枚举值赋予给枚举变量,不能把元素的数值直接赋予枚举变量

typedef声明

用typedef声明新类型名

除了可以直接使用C提供的标准类型名和程序编写者自己声明的结构体,共用体,枚举类型外,还可以用typedef类型指定新的类型来替换已有的类型名,有以下两种情况:

1 简单地用一个新的类型名代替原有的类型名

typedef int intgeter; //用指定的类型名代替int,作用相同

2 命名一个简单的类型名代替复杂的类型表示方法

简单的来说:就是按定义变量的方式,把变量名换上新类型名,并且在最前面加上typedef,就声明了新类型名代替了原来的类型

ref:https://yngzmiao.blog.csdn.net/article/details/80253595

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值