构造类型是一种自定义的数据类型,分为结构体、共用体、枚举。
一、结构体
1.结构体类型的定义
struct 类型名
{
数据类型 变量名1;
数据类型 变量名2;
};//结构体的结尾要加分号
struct Roal
{
char name[30];
short sex;
int age;
};
结构体类型定义时,在分号前加一个变量名,相当于定义了一个全局变量。
struct Roal
{
char name[30];
short sex;
int age;
}g_a;
== struct Roal g_a;
2. 结构体变量的定义
语法:struct 类型名 变量名;
初始化:
1.全部初始化:
struct Roal a={"zhangsan",1,25};
2.部分初始化:(GNU特有语法)
struct Roal b={.name="lisi",.age=20};
3.访问
3.1 直接访问变量(使用 . 运算符)
读:不能整体输出,要依次对应类型输出。
printf("name:%s,sex:%d,age:%d\\n",a.name,a.sex,a.age);
写:对变量进行输入,字符串类型用strcpy修改内容。
a.age=23;
strcpy(a.name,"lisi");
3.2 通过指针访问(使用 -> 运算符)
指针语法:struct 类型名* 指针名 = &变量名;
struct Roal* p=&a;
printf("name:%s,sex:%d,age:%d\\n",p->name,p->sex,p->age);
4.结构体的存储
字节对齐问题:
CPU(32bit)在访问时以4byte为单位访问,效率高。
由于结构体是自定义类型,成员变量根据需要来定义,自定义的成员变量的相对地址不一定在4byte对齐的地址。编译器会把成员变量的地址扩展到4byte对齐的地方,扩大结构体的大小。
字节对齐准则:
- 结构体成员必须存放在起始地址为自身类型大小的整数倍的内存地址。
- 找到结构体中成员变量占用内存最大的。结构体的总大小,应该是最大成员占用内存大小的整数倍。
5.结构体的传参
结构体变量的类型就是自定义的结构体类型。
传地址对变量&操作,传给函数,用结构体类型*指针接收。
#include<stdio.h>
struct Stu
{
char name[30];
int age;
char sex;
};
void show_stu(const struct Stu* p)//对只读参数加上const说明
{
printf("name:%s,age:%d,sex:%c\\n",p->name,p->age,p->sex);
}
int main()
{
struct Stu a={"zhang san",20,'m'};
show_stu(&a);
return 0;
}
6.结构体数组
1.定义结构类型数组
struct Stu a[3]={0};
2.部分初始化(GNU特有)
struct Stu a2[3]={
[1]={.name="lisi",.heigh=1.65}
};
a2[1].heigh=1.88;
3.结构体变量之间可以直接赋值
a2[0]=a2[1];
struct Stu p=a[0];
二、共用体(相对于结构体用的少)
共用体,是为了在早期计算机中,节省内存的一个自定义结构。
共用体也叫联合体,成员变量的内存空间是共享的。结构体中,每个成员变量的内存空间是独立的。结构体的总大小为内存最大的成员变量的大小,一次只能存一个成员变量。
应用:函数参数传递 ,判断存储方式为大端还是小端。
语法:
union 共用体名字
{
数据类型 成员变量1;
数据类型 成员变量2;
…
};
cpu 的字节顺序:
- 大端存储:51,网络。数据的低位在内存的高地址,数据的高位在内存的低地址。
- 小端存储:arm,intel。数据的低位在内存的低地址,数据的高位在内存的高地址

1.用共用体判断
#include <stdio.h>
union End
{
int i;
char c;
};
int main()
{
union End e;
e.i = 0x12345678;
printf("%x\\n",e.c);//输出为78则是小端,输出为12则是大端
return 0;
2.用数组判断
int main()
{
int i = 0x12345678;
char * p = (char*)&i;
printf("%x\\n",*p);
}
三、枚举类型
枚举类型构造时,会把变量的取值范围一个个列举出来,那么变量只能在这个范围内取值。 列举出来的值,被称为枚举值,类型当作整形(int)常量。
语法:enum 枚举类型名 {枚举值列表};
- 枚举值默认从0开始 ,后一个枚举值在前一个枚举值的基础上+1。枚举值的类型为int 常量
- 枚举类型常和switch搭配使用
- 注意枚举类型赋值的时候不要超出范围。 gcc不会有报警,但逻辑上有潜在的错误。
enum WEEK {MON,TUE,WED,THU,FRI,SAT,SUN};
int main()
{
enum WEEK w = FRI; // 变量定义+ 初始化
w = SUN; // w 的类型 是 int
switch(w)
{
case MON:
case TUE:
case WED:
printf("工作日\\n");
break;
case THU:
case FRI:
case SAT:
printf("出差日\\n");
break;
case SUN:
printf("放假\\n");
break;
}
四、位运算
| 运算符 | 含义 |
| &(双目) | 按位与运算符,两个二进制位都为1则1,反之为0 |
| |(双目) | 按位或运算符,两个二进制位有一个为1则1,反之为0 |
| ^(双目) | 按位异或运算符,两个二进制位不同则1,相同为0 |
| ~(单目) | 按位取反,对应的二进制位为1则0,为0则1 |
| << | 逻辑左移,左位舍去,有位补0 |
| >> | 逻辑右移 |
位运算符操作的都是对应数据的二进制位。需要先把数据转换为二进制,再对二进制位进行相关操作(与,或,非等)。
>>右移分为逻辑右移和算术右移:
- 逻辑右移:对于无符号数或者数据为正数,右位舍去,左位补0。
- 算术右移:对于有符号类型的数据且为负数,右位舍去,左位补1。

运算符的应用:
- &运算符:可用于判断某个二进制位是否为0。
与一个对应位为1,其余为0的数。eg:1<<5,第六位二进制位置1,其余置0的数。
- | 运算符:给某个二进制位置1。
与一个对应位为1,其余为0的数。
- ^ 运算符:用于两数交换。
i=i^j;
j=j^i;
i=i^j;
网硕互联帮助中心



评论前必须登录!
注册