c语言编程(1)—— 枚举、结构体、共用体

一、枚举

什么是枚举

 枚举是用关键字enum声明的一种数据类型。

枚举的特点

 a、在内存中占用4字节大小的内存空间,是一个有符号数。(大小)

 b、枚举类型内部可以多个常量(有限),enum类型的取值范围为其中的常量值。(取值范围)

 c、枚举中的常量值可以单独使用,相当于一个普通常量。作用域取决于枚举类型(不是变量)声明的作用域。(作用域)

 d、枚举中的常量第一个默认为0,然后递增加一。如果在某一个常量值定义为x,则下一个为x+1。(默认的常量值)

枚举与宏的比较

 宏:简单的替换,我们可以定义一个标识符等价于一个数,可以是整数、浮点数。
 eg1: #define PAI 3.14
 eg2:#define MAX 100

 枚举:是一个类型,一个取值为有限的数值。内部数值必须int类型。
 eg1:
 enum day {
  MON = 1, TUES = 2, WED = 3, THURS = 4, FRI = 5, SAT = 6,SUN = 7,
 };

 当我们需要使用define定义多个且连续的整数时。使用枚举类型可以使代码变得更加简洁。

开发中的实例

实例1:
 坐标轴的XYZ方向
 enum axis {
  int x,
  int y,
  int z,
 };

实例2:
 传感器的不同类型
 enum sensor {
  int als,
  int accel,
  int hal,
 };

注意

 a、枚举中的值不能作为左值,因为它们是一个常量。

 b、宏在预处理阶段被替换,而枚举类型在编译阶段进行替换成对应的值。可以将枚举类型理解为编译阶段的宏。

二、结构体与位域

什么是结构体

 结构体是用struct关键字声明,其内部可以存放一个或多个不同的数据类型的集合。

结构体的特点

 a、结构体中的成员在内存中连续存储。与数组类似,但不同的是数组是一组相同的数据类型,而结构体中可以为不同的数据类型。(内存分布)

 b、结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),并遵守内存对齐。(大小)

 c、单纯结构体类型不占用内存空间,只有当声明定义了一个结构体变量才会对这个变量分配内存。所以不能对结构体名进行取地址操作。只能对结构体变量进行取地址,且返回的地址为第一个数据成员的地址。(取地址运算)

 d、结构体中的数据成员的访问使用成员运算符(.和->)进行数据的访问。

结构体中的内存对齐

(1)保持4字节对齐。当变量的大小小于4字节,按照4字节补齐。

(2)尽可能的存放多个变量,但不超过4字节。

 实例:
 struct example {
  char a;  //1字节
  short b;   //2字节 a、b共占用4字节(4字节补齐)
  int c;     //4字节
  short d;   //2字节
  char e;   //1字节 d、e共占用4字节(4字节补齐)
 }aa;
 变量aa其大小为12个字节。

位域

 有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可。例如开关只有通电和断电两种状态,用 0 和 1 表示足以,也就是用一个二进位。这时我们可以用位域来进行控制,从而更好的利用内存空间。

位域的特点

 a、在结构体类型中,位域可以改变某个成员变量所占用的二进制位数(即宽度)。一旦宽度发生改变,在使用时成员变量的取值范围不得大于位宽的最大数,否则就会发生数据的截断。

 b、可以使用位域的几种数据类型是 int、signed int 和 unsigned int(int 默认就是 signed int);但编译器在具体实现时都进行了扩展,额外支持了 char、signed char、unsigned char 以及 enum 类型。

 c、位域成员可以没有名称,只给出数据类型和位宽,叫做无名位域。无名位域一般用来作填充或者调整成员位置。因为没有名称,无名位域不能使用。

实例1:
 struct bs{
   unsigned m;
   unsigned n: 4;
   unsigned char ch: 6;
 };

 : 后面的数字用来限定成员变量占用的位数。成员 m 没有限制,根据数据类型即可推算出它占用 4 个字节(Byte)的内存。成员 n、ch 被:后面的数字限制,不能再根据数据类型计算长度,它们分别占用 4、6 位(Bit)的内存。

实例2:
 无名位域
 struct bs{
    int m: 12;
    int : 20; //该位域成员不能使用
    int n: 4;
 };

 如果没有位宽为 20 的无名成员,m、n 将会挨着存储,sizeof(struct bs) 的结果为 4;有了这 20 位作为填充,m、n 将分开存储,sizeof(struct bs) 的结果为 8。

三、共用体

什么是共用体

 共用体是用union关键字修饰的一种复杂类型

共用体的特点

 a、共用体内部的成员共同占用一块内存空间。同一时刻只能保存一个成员的值,如果对其它的成员赋值,就会把原来成员的值覆盖掉。

 b、共用体占用的内存大小等于最长的成员占用的内存。

使用场景

 可以使用共用体检测cpu的储存方式

四 大端方式和小端方式

什么是大端方式和小端方式

 大端和小端是指数据在内存中的存储方式

大端方式

 是指将数据的低位(比如 1234 中的 34 就是低位)放在内存的高地址上,而数据的高位(比如 1234 中的 12 就是高位)放在内存的低地址上。
 实例1:大端方式存储
在这里插入图片描述

小端方式

 是指将数据的低位放在内存的低地址上,而数据的高位放在内存的高地址上。这种存储模式将地址的高低和数据的大小结合起来,高地址存放数值较大的部分。一般pc中采用小端存储方式,网络间使用大端方式。
 实例2;小端方式存储
在这里插入图片描述

检测cpu的储存方式

 使用共用体来检测cpu存储方式是大端还是小端

#include <stdio.h>

int main(){
    union{
        int n;
        char ch;
    } data;
    
    data.n = 0x00000001; //也可以直接写作 data.n = 1;
    if(data.ch == 1){
        printf("Little-endian\n");
    }else{
        printf("Big-endian\n");
    }
    return 0;
}

主机与网络字节序的转换

 TCP/IP 协议规定了在网络上必须采用网络字节顺序(也就是大端模式),而一般的pc采用小端方式存储

#include <arpa/inet.h> 
 
uint32_t htonl(uint32_t hostlong); // 用于将主机 unsigned int 型数据转换成网络字节顺序

uint16_t htons(uint16_t hostshort); // 用于将主机 unsigned short 型数据转换成网络字节顺序

uint32_t ntohl(uint32_t netlong); // 用于将网络字节顺序 unsigned int 型数据转换成主机的小端方式

uint16_t ntohs(uint16_t netshort);// 用于将网络字节顺序 unsigned short 型数据转换成主机的小端方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值