首页 > 其他分享 >C语言之位段、枚举、联合

C语言之位段、枚举、联合

时间:2023-03-20 21:00:39浏览次数:36  
标签:存储 int 成员 C语言 位段 枚举 空间

一、位段

1.1位段的声明

struct 对象名{

    位段的成员列表;(类型 变量名:数字;)

};//别忘记分号

位段与结构体的声明,除了成员列表不同外,其余格式皆相同

首先,位段的成员类型必须是int(unsigned int或者signed interesting)(小于等于int的都可以),

其次,位段的成员名后紧跟着冒号和数字,数字代表着该变量所占比特位的大小,举例:

struct S{
char a:3;
char b:4;
char c:5;
char d:4;
};

位段与结构体的区别无非是在成员列表的要求上稍有不同,限制了每个成员的存储空间,例如上述代码的a只有3个比特位的空间,b只有4个比特位的空间,c只有5个比特位的空间,a,b,c各自使用自己的空间来存储自身相应的数据,当自身数据太大超出自身分配空间大小时,只能存储数据的一部分,而当开辟剩余空间不足以完全存储一个成员变量时,则会重新开辟空间

1.2位段的内存分配

当位段成员是int类型时,每次开辟4个字节大小的空间,(当位段成员是char类型时,每次开辟1个字节大小的空间),然后依次存储位段成员,当剩余空间不够完整存储下一个成员时,再开辟一个4个字节大小的空间来存储,但是位段成员在利用这4个字节大小的空间时,是从左到右,还是从右到左,并没有做出规定,我们假设是从右到左利用

例如

struct S{
char a:3;
char b:4;
char c:5;
char d:4;
};
int main()
{
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
printf("%d ",sizeof(s));
}

因为是位段,而且成员是char,因此每次开辟1个字节的空间,8个比特位,初始化s全部为0,因此如下

C语言之位段、枚举、联合_赋值

初始化a=10,a的二进制为1010,但只给a分配了3个比特位的空间,不能完全存储的下,因此只能从低字节到高字节存储a的3个比特位,即010,如下

C语言之位段、枚举、联合_数据_02

b=12,二进制为1100,b的空间是4个比特位,可以存储,如下

C语言之位段、枚举、联合_赋值_03

c=3,二进制为11,第一次开辟的8个比特位空间只剩下一个,不足以完全存储c,因此重新开辟一个字节的空间来存储c,且c一共占据5个比特位的空间

C语言之位段、枚举、联合_位段_04

d=4,且占据4个比特位,剩余3个比特位不够,因此重新开辟空间存储d,二进制为0100

C语言之位段、枚举、联合_赋值_05

那么,位段变量s在内存中存储的二进制位应为0110 0010 0000 0011 0000 0100,转化为16进制为  62 03 04 ,我们来看一下调试结果

C语言之位段、枚举、联合_赋值_06

我们再来看看成员是int类型的位段所占空间大小

struct A
{
int a:2;
int b:5;
int c:10;
int d:30;
};

成员是int类型,首先开辟四个字节的空间,分别存放a,b,c后,剩余的空间不足以存储d,因此再次开辟4个字节的空间来存储d,一共8个字节,来看看调试结果

C语言之位段、枚举、联合_赋值_07

1.3位段小结

位段的使用能够让程序员更加合理的利用空间,但是它本身也存在着一定的问题

  1. int 位段被当成有符号数还是无符号数是不确定的。也就是说int类型数据二进制位的首位是否被当作符号位不确定,有兴趣的可以亲自测试一下
  2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题。)这个好理解,成员类型所占字节数就是最大位的数目,但是不同机器下相同类型所占字节不同(int)

  1. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。但是我们可以亲自实验
  2. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。个人理解为位段中包含一个位段时,开辟空间的剩余位不足以完整存储分配给成员位段的位时,不确定会这么进行存储,当然,如果成员不是位段时,此时肯定会再开辟空间(舍弃)

二、枚举

2.1枚举的声明

enum 对象名{

枚举成员列表;//准确来说是枚举对象的可能取值

//直接书写变量名,无需书写类型

};

枚举的声明和结构体的声明相比,除了关键字从enum变为struct以及成员无需类型名外,其余书写格式均相同,但枚举和结构体不同的是,

枚举的含义表示可以一一列举,因此如果不给枚举的成员赋值,那么从第一个枚举成员开始,会默认为0,第二个为1,第三个为2,以此类推,如果在某个枚举成员处赋值,那么它之前的成员不受影响,之后的成员会在它的基础上递增,因此

我们经常把枚举的成员称之为枚举常量,它们是枚举对象所有可能的取值

并且枚举常量前虽然没有书写类型,但是它们本身是有类型的,他们的类型就是enum 对象名。

2.2枚举的优点

  1. 增加代码的可读性和可维护性。看到枚举就能明白它是什么
  2. 和#define定义的标识符比较枚举有类型检查,更加严谨。当我们用define定义某个常量时,其实该常量只是一个标识符,在接下来的代码中,我们只要看到这个常量的名字,就会自动转化为define定义时该常量对应的内容。所有说define定义的数据其实没有类型,而枚举常量是有类型的
  3. 防止了命名污染(封装)。命名污染的意思就是名字重复出现
  4. 便于调试。源代码->预编译->编译->链接->可执行程序,预编译的作用就是去除注释以及转化define定义的标识符这些冗余的东西。枚举的存在可以代替define,使得代码更加便于调试
  5. 使用方便,一次可以定义多个常量。使用一次枚举,可以同时定义多个枚举常量,比define定义更加方便

2.3枚举的使用

只能用枚举常量或者强制转化为枚举类型来给枚举变量赋值

enum Color//颜色

{

RED=1,

GREEN=2,

BLUE=4

};
int main()
{
enum Color clr = RED;
//enum Color clr = (enum Color)1;
}

三、联合(联合体)(共用体)

3.1联合体的声明

union 对项名{

成员列表;

};

3.2联合体的特点

所有成员共用一块空间,即每个成员的起始地址相同,然后按照本身大小向后存储

C语言之位段、枚举、联合_数据_08

3.3联合体的大小

联合体的大小最小是联合的大小至少是最大成员的大小。因为联合体的特点就是共用空间,当能存储最大的那个时,其他的肯定没问题

当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。这里的最大对齐数就是自身对齐数和默认对齐数(8)中的较小值,

​union Un1
{
char c[5];//c前面的类型是1,因此自身对齐数为1,和8比较后的较小值为1
int i; //比较后的对齐数为4
};//最大对齐数为4,但不能存储数组c(5),因此翻倍,为8


union Un2
{
short c[7];//比较后对齐数为2
int i;//比较后对齐数为4
};//最大对齐数为4,但不能存储数组c(14),所以为16

C语言之位段、枚举、联合_位段_09

调试结果如上

标签:存储,int,成员,C语言,位段,枚举,空间
From: https://blog.51cto.com/u_15466618/6138632

相关文章

  • 实验2 C语言输入输出和控制语句应用编程
    #include<stdio.h>#include<stdlib.h>#include<time.h>#defineN5#defineR1586#defineR2701intmain(){intnumber;inti;srand(time(0));......
  • 如何用C语言对十亿数据排序大体就是用分块法把十亿个随机数据排序?
    分析过程将十亿个数据按照一定的规则分成若干个块,每个块包含M个数据,其中M是一个适当的大小,可以根据实际情况进行调整。1、对每个块内的数据进行排序,可以使用快速排序、归......
  • c语言http文件下载断点续传示例(libcurl)
    以下是C语言实现HTTP文件下载的断点续传示例代码。假设要下载的文件URL为​​http://example.com/example.zip,本地保存为​​example.zip。#include<stdio.h>#incl......
  • 用C语言实现通讯录(初级版本)全部代码
    注意:分别用test.c(主函数),contact.c(函数实现),contact,h(函数声明)实现代码test.c#define_CRT_SECURE_NO_WARNINGS1#include"contact.h"voidmenu(){printf("**************......
  • 堆排序——C语言描述
    堆排序——C语言描述目录堆排序——C语言描述0测试用例框架1定义2代码4测试用例0测试用例框架https://blog.csdn.net/m0_59469991/article/details/127137119?csdn......
  • C语言学习第二天
    1、#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>intmain(){chararr1[]="abc";//"abc"--'a''b''c''\0',\0表示字符串的结束标志//数据在计算机上存储的时......
  • C语言函数大全--b开头的函数
    C语言函数大全本篇介绍C语言函数中b开头的函数1.bar1.1函数说明函数声明函数功能voidbar(intleft,inttop,intright,intbottom);画一个二维条形图......
  • 暴力枚举正方形、长方形
    #include<bits/stdc++.h>usingnamespacestd;longlongn,m,nn,mm,zfx,cfx;//n、m为长宽intmain(){cin>>n>>m;nn=n;mm=m;while(mm>=1&&nn>=1......
  • C语言中%d,等等% 的用法,和意义
      转载-----%d是占位符,%是引导符,d表示十进制整数的形式例如我用键盘输入一个整数给变量a写成:scanf("%d",&a);%d占得就是a的位再如我在显示器上输出变量a的值......
  • C语言_求最大公约数和最小公倍数
    #include<stdio.h>intmain(){ intn1,n2,x,y,temp;printf("请输入两个数用空格隔开:\n"); scanf("%d%d",&n1,&n2); x=n1>n2?n1:n2;//保存较大数 y=n1+n2-x; ......