首页 > 其他分享 >C语言结构体位域简单介绍

C语言结构体位域简单介绍

时间:2023-04-28 09:44:07浏览次数:45  
标签:p1 struct int C语言 char 体位 简单 example 结构

目录
历史文章

0 前言

这几天看到一个有趣的结构体,之前没有见过,稍微了解了一下,顺便记录一下

以下例子均在32位操作系统操作

1 结构体简单介绍

在C语言中,每种类型的变量都会占用一定的字节数,以下面几种为例

char 1B
int 4B
double 8B

结构体简单将就是,用户自定义的复合数据类型,一个结构体中可以包含多种数据类型,最为常见的例子,就是学生信息表

结构体的声明方式如下

struct 结构体名称{
    
    类型 成员1;
    类型 成员2;
     
    ...
};

那么问题来了,结构体可以包含多种数据类型,那一个定义好的结构体会占用多少字节

比如下面这个例子

#include <stdio.h>

struct example{
	int a;
	int b;
	double c;
};

int main () {
	
	printf("Size of example is %0d\n", sizeof(struct example));
	return 0;
}

在main函数中用sizeof打印一下结构体占用的字节数

先猜一下,int占4B,double占8B,计算下来应该是16B,来看运行结果

运行结果与预期相符

2 结构体的内存对齐

在CPU的存取的方式是以32bit(4 byte)为一次存取,也就是说,无论给定的data位宽为多少,CPU一次固定存取的位数固定为32bit

如果有数据超过32bit,CPU则会分多次存取

以下图为例,绿色的方框代表32bit

char的长度是1byte,2个char型变量共2 byte,没有超过32bit,所以CPU可以一次存取,因此这两个char型变量的地址偏移是连续的

下面用代码佐证

#include <stdio.h>

struct example{
	char a;
	char b;
	
};

int main () {
	
	struct example p1;
	
	printf("a: %0d\n", (size_t)&p1.a);
	printf("b: %0d\n", (size_t)&p1.b);
	return 0;
}

仿真结果如下

可以看到,地址偏移数增加1

这里强调一下,在计算机的地址中,是以byte为单位的

接下来换个图

就像这样,如果在char后紧接着是一个int变量,那么此时结构体总共占用多少字节,int的地址偏移又是多少

#include <stdio.h>

struct example{
	char a;
	int b;
	
};

int main () {
	
	struct example p1;
	
	printf("\tSize of example is %0d\n", sizeof(p1));
	printf("\ta: %0d\n", (size_t)&p1.a);
	printf("\tb: %0d\n", (size_t)&p1.b);
	return 0;
}

先来猜测一下,如果不考虑内存对齐的因素,char占1 byte,int占4 byte,那结构体总的长度应该是5 byte

结果如下

可以看到二者的地址偏移并不是连续的,变量b的起始地址在a的下一个4 byte(地址偏移是负数)

并且,此时结构体的总长度是8 byte

3 结构体位域

下面来介绍一下结构体位域

结构体位域是用来将内存扣到极致的东西,在结构体位域中,可以自定义每个变量的位宽,并且是以bit为单位的

#include <stdio.h>

struct example{
	 char  a : 5;
	 char  b : 3;
	
};

int main () {
	
	struct example p1;
	
	printf("\tSize of example is %0d\n", sizeof(p1));
	return 0;
}

在位域中,重新定义了a占 5 bit ,b占3 bit,那么整个结构体总共8bit,也就是1 byte

如果没有指定位域呢

#include <stdio.h>

struct example{
	 char  a ;
	 char  b ;
	
};

int main () {
	
	struct example p1;
	
	printf("\tSize of example is %0d\n", sizeof(p1));
	return 0;
}

结果如下

本来打算打印下每个结构体成员的地址偏移的,结果

image-20230420235839679

不让打印,无法获取地址 >_<

原文连接


标签:p1,struct,int,C语言,char,体位,简单,example,结构
From: https://www.cnblogs.com/ICcode/p/17360982.html

相关文章

  • 1v1&2v2简单变种国际象棋例子
    活动包括的两个项目:2vs2对局1vs1对局2vs2模式-CrazyNopromotionteams游戏设置:需要一个游戏发起人,下面是游戏发起人操作,其他玩家只要在变体象棋界面选择同意邀请即可。进入变体国际象棋界面:点4playerchess(或者列表中除了doubles这一栏之外的另一个变体玩法的标......
  • BFS 简单应用
    前言:BFS即广度优先搜索(或宽度优先搜索),具体定义和实现不在赘述。本文所有代码前的开头头文件,宏定义和命名空间如下(只是一些常用的define和一个快读):#include<bits/stdc++.h>#defineTptemplate<typenameTy>#defineTstemplate<typenameTy,typename...Ar>#definell......
  • 菜鸟记录:c语言实现PAT甲级1005--Spell It Right
     非常简单的一题了,但还是交了两三次,原因:对数组的理解不足;对数字和字符之间的转换不够敏感。这将在下文中细说。Givenanon-negativeinteger N,yourtaskistocomputethesumofallthedigitsof N,andoutputeverydigitofthesuminEnglish.InputSpecificatio......
  • C语言--练习
    1、写一个函数输出a的二进制(补码)中1的个数。intcount_(inta){ intcount=0; for(inti=0;i<32;i++) { if(((a>>i)&1)==1) count++; } returncount;}intmain(){ intcount=0; inta=0; scanf("%d",&a); count=count_(a);......
  • C++实现一个简单的生产者-消费者队列
    本文的代码都是ChatGPT生成,我只是做了微小的调整和整合,AI提示词如下:设计一个C++类,支持生产者-消费者模型,可以通过size函数获取剩余数量可能第一次生成的不一定合适,多刷新几次。生成的ProducerConsumerQueue.h代码如下:#ifndefPRODUCER_CONSUMER_QUEUE_H#definePRODUCER_CON......
  • C语言处理特定字符串
    C语言处理特定字符串在使用NiosIDE实现串口助手向NiosII系统发送数据时,再将数据发送至FPGA逻辑模块,以此控制LED灯。在串口助手中发送14568936的数据,Nios接收到的数据是形如"14568936\r\n"的字符串,默认以\r\n结尾,要将此字符串转化为四个整型数据。#include<stdio.h>......
  • [每天例题]蓝桥杯 C语言 单词去重
    单词去重题目https://www.lanqiao.cn/problems/2302/learning/?page=1&first_category_id=1&sort=students_count&name=%E5%8D%95%E8%AF%8D思路分析1.建立一个数组,注意数组的容纳范围,在这里有一个数据挖坑2.通过字符串函数,我们可以进行单词的重复判断,并完成去重处理代码 ......
  • flask简单实现
    一、flask简介二、flask安装及简单实现三、问题 一、flask简介Flask本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用第三方的扩展来实现。比如可以用Flask扩展加入ORM、窗体验证工具,文件......
  • eclipse创建一个简单的MyBatis项目
    1.创建一个web应用程序 2.输入项目名称 3.在lib文件夹中添加jar包 4.在src文件夹中创建com.demo.po,com.demo.mapper,com.demo.dao三个包,并创建MyBatis框架配置文件mybatis-config.xml文件,在mapper目录下创建数据实体映射文件CommodityStorageMapper.xml,在po目录下创建名为......
  • 用C++编写一个简单的发布者和订阅者
    摘要:节点(Node)是通过ROS图进行通信的可执行进程。本文分享自华为云社区《编写一个简单的发布者和订阅者》,作者:MAVER1CK。@[toc]参考官方文档:Writingasimplepublisherandsubscriber(C++)背景节点(Node)是通过ROS图进行通信的可执行进程。在本教程中,节点将通过话题(To......