目录
1、联合体
1.1、联合体简介
联合体、共用体union,联合体的声明和结构体类似,联合体(union)和结构体(struct)同样可以包含多种数据类型和变量,但与结构体的功能却不同,联合体中所有成员共用同一块内存,系统为联合体中最大的成员分配内存,结构体是每一个成员都要分配内存,结构体需要注意的是内存对齐的问题。
总结:
1.结构体成员变量空间是独立的
2.共用体成员变量空间是共享的
int main(void)
{
union data
{
int a;
char b;
float c;
double d;//联合体为最大成员的开辟空间,其他成员共用此空间
};
struct stu
{
int num;
char name;
int age;// struct 为所有成员开辟空间
};
union data x;
struct stu Li;
printf("联合体data占用内存%d\n",sizeof(x));
printf("结构体stu占有内存%d\n",sizeof(Li));
return 0;
}
联合体data占用内存8
结构体stu占有内存12
联合体union分配的同一块内存,被翻译成不同类型的数据,且翻译的类型取决于定义的数据类型。简单来说,就是编译器为联合分配了空间,空间中存储什么类型的数由操作者定义。
#include <stdio.h>
int main(void)
{
union fi
{
int a;
char b;
float c;
}fi;
fi.a=10;
printf("a=%d\n",fi.a);
fi.b='w';
printf("b=%c\n",fi.b);
fi.c=3.1415;
printf("c=%lf\n",fi.c);
return 0;
}
a=10
b=w
c=3.141500
1.2、联合体的优缺点
联合体(union)中是各变量是“互斥”的——优点是内存使用更为精细灵活,也节省了内存空间。
共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉, 由于使用共用体的时候,必须记住当前存放在联合共用体变量中的是哪个成员,有很多不便。
共用体可以有很多的访问内存的手段,使用起来非常灵活,但是不同的访问之间没有互相进行屏蔽,这有时候会导致逻辑上的错误,比如成员占用的地址不一样多时,访问可能会导致乱码的情况。
1.3、联合体的应用
union的使用场合,是各数据类型各变量占用空间差不多并且对各变量同时使用要求不高的场合。
如何判断一个平台为内存大端?内存小端?
#include <stdio.h>
union s {
char a;
int b;
};
int main(int argc, const char *argv[])
{
union s s1;
s1.b = 1;
if (s1.a)
{
printf("小端!\n");
}
else
{
printf("大端!\n");
}
return 0;
}
#include<stdio.h>
union var{
char c[4];
int i;
};
int main(){
union var data;
data.c[0] = 0x04;//因为是char类型,数字不要太大,算算ascii的范围~
data.c[1] = 0x03;//写成16进制为了方便直接打印内存中的值对比
data.c[2] = 0x02;
data.c[3] = 0x11;
//数组中下标低的,地址也低,按地址从低到高,内存内容依次为:04,03,02,11。总共四字节!
//而把四个字节作为一个整体(不分类型,直接打印十六进制),应该从内存高地址到低地址看,0x11020304,低位04放在低地址上。
printf("%x\n",data.i);
}
内存大小端:
1.内存低地址存放低数据位称为内存小端
2.内存低地址存放高数据位称为内存大端
2、枚举
2.1、枚举的基本概念
枚举(enum)就是英文enumerate的缩写,也就是列举、排列说明的意思。枚举类型是C语言中的一种特殊类型,枚举类型可以让我们的程序使用一些固定长度和固定数值的变量值范围。
enum 枚举类型名 {
枚举常量1,
枚举常量2,
枚举常量3,
...
};
//枚举颜色
enum color{red=1, oreange=2, yellow=3, green=4, ching=5, blue=6, purple=7};
//枚举一个星期的每一天
enum week
{
Su, Mo, Tu, We, Th, Fr, Sa
};
//枚举每一个月
enum month
{
January, February, March, April, May, June, July, August, September, October, November, December
};
枚举类型的基本实现原理。实际上在使用关键字enum创建枚举类型并编译后,编译器会为我们生成一个相关的类。
结论:从反编译的代码可以看出编译器确实帮助我们生成了一个Day类而且该类继承自java.lang.Enum类,该类是一个抽象类,除此之外,编译器还帮助我们生成了7个Day类型的实例对象分别对应枚举中定义的7个日期。还为我们生成了两个静态方法,分别是values()和 valueOf(),到此我们也就明白了,使用关键字enum定义的枚举类型,在编译期后,也将转换成为一个实实在在的类,而在该类中,会存在每个在枚举类型中定义好常量的对应实例对象
2.2、枚举的应用
输入数字判断为星期几?利用枚举减少重复定义变量。
#include <stdio.h>
int main()
{
enum weekday
{
mon=1,
tue,
wed,
thu,
fri,
sat,
sun
} day;
int i;
printf("请输入1到7的数:");
scanf("%d",&i);
day=(enum weekday)i;
switch(day)
{
case sun: printf("sunday\n");break;
case mon: printf("monday\n");break;
case tue: printf("tuesday\n");break;
case wed: printf("wednesday\n");break;
case thu: printf("thursday\n");break;
case fri: printf("friday\n");break;
case sat: printf("satday\n");break;
default: printf("input error\n");break;
}
}
枚举功能菜单
/* 按键选项枚举类型 */
enum menu_button {
PLAY_PAUSE_BTN = 1, //开始/暂停按键
STOP_BTN, //停止按键
PRE_BTN, //上一首按键
NEXT_BTN, //下一首按键
ADD_SPEED_BTN, //倍速按键
EXIT_BTN, //退出按键
};
/* 播放状态枚举类型 */
enum play_stat {
FREE_STAT, //空闲状态
PLAYING_STAT, //播放状态
PAUSE_STAT, //暂停状态
};
/* 播放速度枚举类型 */
enum play_speed {
ONE_SPEED, //一倍速
TWO_SPEED, //二倍速
};
/* 当前播放状态 */
enum play_stat curstat = FREE_STAT;
枚举的优点:
- 增加代码的可读性
- 便于调试
- 使用方便,一次可以定义多个常量
- 封装思想,防止命名污染
注意:
1.当某个类型有若干个值,并且只能在值域中选择其一的可以使用枚举类型
2.枚举常量值为int类型,且每个常量的值均为上一个常量的值+1
第一个常量值默认为0
3.枚举常量可以理解为#define 定义的常量宏
3、字符串
3.1、字符串的输入
输入输出字符串函数:
- gets(),直接输入字符串,只能输入字符串
- fgets(),第三个参数控制从什么地方获得字符串
- scanf(),通过格式控制符%s输入字符串
- puts(),直接输出字符串,只能输出字符串
- fputs(),输出字符串不为输出添加换行符
- printf(),通过格式控制符%s输出字符串
- gets(char *s)
gets()从系统的标准输入设备(stdin)获得一个字符串,字符串没有预定长度,当遇到第一个换行符(\n)结束输入,且读取换行符之前的字符,在字符后添加空字符(\0)。
#include <stdio.h>
#define N 64
int main(void)
{
char str[N];
char *ptr;//指向str的指针
ptr=gets(s