struct详解

高等数学(预备知识之对数函数) 对数函数 阅读详情
1. struct的巨大作用
  在网络协议、通信控制、嵌入式系统的C/C++编程中,我们经常要传送的不是简单的字节流(char型数组),而是多种数据组合起来的一个整体,其表现形式是一个结构体。


  经验不足的开发人员往往将所有需要传送的内容依顺序保存在char型数组中,通过指针偏移的方法传送网络报文等信息。这样做编程复杂,易出错,而且一旦控制方式及通信协议有所变化,程序就要进行非常细致的修改。


  一个有经验的开发者则灵活运用结构体,举一个例子,假设网络或控制协议中需要传送三种报文,其格式分别为packetA、packetB、packetC:


struct structA
{
int a;
char b;
};


struct structB
{
char a;
short b;
};


struct structC
{
int a;
char b;
float c;
}
  优秀的程序设计者这样设计传送的报文:


struct CommuPacket
{
int iPacketType;  //报文类型标志
union      //每次传送的是三种报文中的一种,使用union
{
  struct structA packetA;
  struct structB packetB;
  struct structC packetC;
}
};
  在进行报文传送时,直接传送struct CommuPacket一个整体。


  假设发送函数的原形如下:


// pSendData:发送字节流的首地址,iLen:要发送的长度
Send(char * pSendData, unsigned int  iLen);
发送方可以直接进行如下调用发送struct CommuPacket的一个实例sendCommuPacket:
Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );
假设接收函数的原形如下:
// pRecvData:发送字节流的首地址,iLen:要接收的长度
//返回值:实际接收到的字节数
unsigned int Recv(char * pRecvData, unsigned int  iLen);
  接收方可以直接进行如下调用将接收到的数据保存在struct CommuPacket的一个实例
recvCommuPacket中:


Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );
  接着判断报文类型进行相应处理:


switch(recvCommuPacket. iPacketType)
{
    case PACKET_A:
    …    //A类报文处理
    break;
    case PACKET_B:
    …   //B类报文处理
    break;
    case PACKET_C:
    …   //C类报文处理
    break;
}
  以上程序中最值得注意的是


Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );
Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );
  中的强制类型转换:(char *)&sendCommuPacket、(char *)&recvCommuPacket,先取地址,再转化为char型指针,这样就可以直接利用处理字节流的函数。


  利用这种强制类型转化,我们还可以方便程序的编写,例如要对sendCommuPacket所处内存初始化为0,可以这样调用标准库函数memset():


memset((char *)&sendCommuPacket,0, sizeof(CommuPacket));


2. struct的成员对齐
  Intel、微软等公司曾经出过一道类似的面试题:


1. #i nclude <iostream.h>


2. #pragma pack(8)
3. struct example1
4. {
5. short a;
6. long b;
7. };


8. struct example2
9. {
10. char c;
11. example1 struct1;
12. short e;   
13. };
14. #pragma pack()


15. int main(int argc, char* argv[])
16. {
17. example2 struct2;


18. cout << sizeof(example1) << endl;
19. cout << sizeof(example2) << endl;
20. cout << (unsigned int)(&struct2.struct1) - (unsigned int)(&struct2)
<< endl;


21. return 0;
22. }
  问程序的输入结果是什么?


  答案是:


8
16
4


  不明白?还是不明白?下面一一道来:


2.1 自然对界


  struct是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如array、struct、union等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。


  自然对界(natural alignment)即默认对齐方式,是指按结构体的成员中size最大的成员对齐。


  例如:


struct naturalalign
{
char a;
short b;
char c;
};
  在上述结构体中,size最大的是short,其长度为2字节,因而结构体中的char成员a、c都以2为单位对齐,sizeof(naturalalign)的结果等于6;


  如果改为:


struct naturalalign
{
char a;
int b;
char c;
};
  其结果显然为12。


2.2指定对界


  一般地,可以通过下面的方法来改变缺省的对界条件:


  · 使用伪指令#pragma pack (n),编译器将按照n个字节对齐;
  · 使用伪指令#pragma pack (),取消自定义字节对齐方式。


  注意:如果#pragma pack (n)中指定的n大于结构体中最大成员的size,则其不起作用,结构体仍然按照size最大的成员进行对界。


  例如:


#pragma pack (n)
struct naturalalign
{
char a;
int b;
char c;
};
#pragma pack ()
  当n为4、8、16时,其对齐方式均一样,sizeof(naturalalign)的结果都等于12。而当n为2时,其发挥了作用,使得sizeof(naturalalign)的结果为8。


  在VC++ 6.0编译器中,我们可以指定其对界方式,其操作方式为依次选择projetct >setting > C/C++菜单,在struct member alignment中指定你要的对界方式。

                                   图1:在VC++ 6.0中指定对界方式

  另外,通过__attribute((aligned (n)))也可以让所作用的结构体成员对齐在n字节边界上,但是它较少被使用,因而不作详细讲解。


2.3 面试题的解答


  至此,我们可以对Intel、微软的面试题进行全面的解答。


  程序中第2行#pragma pack (8)虽然指定了对界为8,但是由于struct example1中的成员最大size为4(long变量size为4),故struct example1仍然按4字节对界,struct example1的size为8,即第18行的输出结果;


  struct example2中包含了struct example1,其本身包含的简单数据成员的最大size为2(short变量e),但是因为其包含了struct example1,而struct example1中的最大成员size为4,struct example2也应以4对界,#pragma pack (8)中指定的对界对struct example2也不起作用,故19行的输出结果为16;


  由于struct example2中的成员以4为单位对界,故其char变量c后应补充3个空,其后才是成员struct1的内存空间,20行的输出结果为4。



3. C和C++间struct的深层区别
  在C++语言中struct具有了“类” 的功能,其与关键字class的区别在于struct中成员变量和函数的默认访问权限为public,而class的为private。


  例如,定义struct类和class类:


struct structA
{
char a;
…
}
class classB
{
      char a;
      …
}
  则:


struct A a;
a.a = 'a';    //访问public成员,合法
classB b;
b.a = 'a';    //访问private成员,不合法
  许多文献写到这里就认为已经给出了C++中struct和class的全部区别,实则不然,另外一点需要注意的是:


  C++中的struct保持了对C中struct的全面兼容(这符合C++的初衷——“a better c”),因而,下面的操作是合法的:


//定义struct
struct structA
{
char a;
char b;
int c;
};
structA a = {'a' , 'a' ,1};    //  定义时直接赋初值
  即struct可以在定义的时候直接以{ }对其成员变量赋初值,而class则不能,在经典书目《thinking C++ 2nd edition》中作者对此点进行了强调。


4. struct编程注意事项
  看看下面的程序:


1. #i nclude <iostream.h>


2. struct structA
3. {
4. int iMember;
5. char *cMember;
6. };


7. int main(int argc, char* argv[])
8. {
9. structA instant1,instant2;
10.char c = 'a';
   
11. instant1.iMember = 1;
12. instant1.cMember = &c;


13.instant2 = instant1;


14.cout << *(instant1.cMember) << endl;


15.*(instant2.cMember) = 'b';


16. cout << *(instant1.cMember) << endl;


17. return 0;
}
  14行的输出结果是:a
  16行的输出结果是:b


  Why?我们在15行对instant2的修改改变了instant1中成员的值!


  原因在于13行的instant2 = instant1赋值语句采用的是变量逐个拷贝,这使得instant1和instant2中的cMember指向了同一片内存,因而对instant2的修改也是对instant1的修改。


  在C语言中,当结构体中存在指针型成员时,一定要注意在采用赋值语句时是否将2个实例中的指针型成员指向了同一片内存。


  在C++语言中,当结构体中存在指针型成员时,我们需要重写struct的拷贝构造函数并进行“=”操作符重载。

 

对数函数 对数函数,对数函数性质,对数函数与指数函数 阅读详情

相关推荐

FPGA优质开源项目 – UDP万兆光纤以太网通信

本文开源一个FPGA项目:UDP万兆光通信。文章末尾有该工程源码获取方式,有需要的小伙伴可以点赞、分享支持一下~

cjx_csdn的博客 4766

[C++] 结构体Struct类型和变量定义

一:struct 和typedef struct的区别 1.首先介绍一下C语言的用法: //定义一个结构体类型 //定义一个数据类型,固定大小内存块的别名,还没有分配内存 struct Teacher { int age; }; void main() { struct Teacher Zhang; //告诉C编译器给我分配内存 } 注意:这里不能省略struct (C++可以),可以采用下面重定义的方式省略struct //定义一个结构体类型 //定义一个数据类型,固定大小内存块的别名,.

Loewen丶的小窝 1万+

CrackerXI+脱壳实战:解决iOS应用逆向中的加密文件问题

本文详细介绍了如何使用CrackerXI+工具对iOS应用进行脱壳,解决App Store应用因FairPlay DRM加密而无法进行静态分析的难题。通过图形化界面一键操作,CrackerXI+能高效获取解密后的可执行文件,为逆向工程奠定基础。文章涵盖工具选型、实战步骤及常见问题排查,是iOS逆向入门与进阶的实用指南。

seed的博客 258

【C语言】1. 结构体struct(结构体概念、结构体指针、结构体作为函数参数、传值与传地址、内存对齐(struct与union))

/创建结构体模板 struct Student {int _age;//使用该模板创建3个变量stu1,stu2,stu3 struct Student stu1 , stu2 , stu3;缺点就是定义变量时必须带上struct可以使用typedef进行简写,这样在定义变量时比较简洁//结构体模板struct Student重新命名为Stu typedef struct Student {int _age;} Stu;

瞌睡的博客 1万+

tanner2019安装教程

tanner2019安装教程 tanner安装包 软件由老师提供,但由于老师给的方法不知怎么回事无法使用就自己找了一些方法,本教程仅提供参考 链接:https://pan.baidu.com/s/1A2O6JuEF8YFbe8bPnD3J6w 提取码:ysif 复制这段内容后打开百度网盘手机App,操作更方便哦 安装过程 1.选择TannerTools_v2019.2-Win64.exe,进行安装。 2.选择安装产品 3.选择目标路径 4.确认安装 5.安装成功,退出。 获取许可过程 1.打开key压缩

weixin_47730560的博客 1万+

Windows下MMdetection3D保姆级安装指南(含CUDA和PyTorch版本避坑)

本文提供Windows平台下MMdetection3D的完整安装指南,重点解决CUDA与PyTorch版本匹配问题。从环境准备到关键组件安装,详细介绍了CUDA Toolkit选择策略、PyTorch精准安装步骤,以及MM系列组件的安装顺序和常见错误解决方案,帮助用户顺利完成3D目标检测环境的配置。

weixin_42628941的博客 490

全面讲解 C 语言的结构体(struct),一网打尽

点击蓝字关注我们因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络,侵删结构体的定义结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。结构体和其他类型基础数据类型一样,例如 int 类型,char类型;只不过结构体可以做成你想要的数据类型,以方便日后的使用。在实际项目中,结构体是大量存在的。研发人员常使用结构体来封装一些属性来组成新...

轻松学C语言 1万+

Stable Diffusion跑图总爆显存?别急着换显卡,试试这个PYTORCH_CUDA_ALLOC_CONF参数调优

本文深入解析了Stable Diffusion运行中常见的显存不足问题,特别是由显存碎片化导致的假性OOM现象。通过详细讲解PYTORCH_CUDA_ALLOC_CONF参数中的max_split_size_mb设置技巧,提供了一套完整的显存优化方案,帮助用户在无需升级硬件的情况下显著提升AI绘画的稳定性与效率。

weixin_42524100的博客 347

python之struct详解_python学习之struct模块

class struct.Struct(format)返回一个struct对象(结构体,参考C)。该对象可以根据格式化字符串的格式来读写二进制数据。第一个参数格式化字符串可以指定字节的顺序。默认是根据系统来确定,也提供自定义的方式,只需要在前面加上特定字符即可:struct.Struct(‘>I4sf‘)特定字符对照表附件有。常见方法和属性:struct.pack(fmt, v1, v2, ...

weixin_31582915的博客 1353

告别复杂模型:用UFLD算法5分钟搞定车道线检测(附Python代码)

本文介绍了UFLD(Ultra Fast Lane Detection)算法在车道线检测中的高效应用,仅需5行核心代码即可实现实时检测,特别适合边缘计算设备。通过对比传统方法,UFLD在推理速度、模型大小和硬件需求上具有显著优势,是深度学习领域轻量级解决方案的典范。

weixin_27872611的博客 287

深入解析经典蓝牙连接:从HCI命令到LMP协议的完整流程

本文深入解析经典蓝牙连接的完整流程,从设备发现、寻呼建立物理链路,到安全配对与加密的每一步。通过对照HCI LOG与AIR LOG,详细拆解了HCI命令与LMP协议报文的对应关系,帮助开发者精准定位连接问题,掌握蓝牙调试的核心方法。

weixin_29260291的博客 450

python之struct详解

python之struct详解

998

脉冲变压器电感选型参数,结构原理,工艺与注意问题总结

脉冲变压器电感简称脉冲变压器,是一种特殊类型的变压器,主要用于处理脉冲信号。它的主要特性是能够在短时间内承受高电压和大电流。脉冲变压器主要用于开关电源、脉冲功率放大、雷达脉冲调制等领域。本文对脉冲变压器的工作原理,结构特点,工艺流程,选型参数及设计注意事项进行总结。

fydar的博客 1342

[SystemVerilog] Struct

struct是一种用户定义的复合数据类型,允许将多个不同类型的成员组合在一起,形成一个逻辑单元。每个成员占用独立的存储空间,访问时通过点号()引用。与联合体(union)struct的成员独立存储,union的成员共享存储空间。与类(class)struct是静态类型,支持综合;class是动态类型,仅用于验证。与数组struct支持异构成员,数组成员类型相同。struct的基本用法是定义一组相关成员,并在代码中访问这些成员。SystemVerilog 的struct。

S&Z3463的博客 1549

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

8、Struct函数

本文介绍了Hive中Struct类型相关函数的使用方法。主要包括FIELD(获取结构体成员值)、INLINE(展开结构体数组)、NAMED_STRUCT(创建带命名的结构体)和STRUCT(创建匿名结构体)四个函数,并提供了每个函数的语法格式和具体SQL示例。这些函数可以方便地创建和操作结构体数据类型,实现类似Java对象的功能,适用于复杂数据结构的处理场景。

lydms的博客 1万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

golang中struct

前面已经介绍的数组,slice,map有一定的相同之处,即处理的都是相同类型的元素,map中的key和value属于相同的类型,但如果要把多个类型的元素放到一起进行处理,则要使用go语言为我们提供的数据结构structstruct非常适合定义一个有意义的对象,可以用于定义属性和方法,这和c语言的结构体,java,class类有些相似。当然struct肯定不是classstruct也是复合类型,而非引用类型,复合类型和引用类型是有区别的,复合类型是值传递,引用类型是引用传递。

ens160的博客 3410

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Golang中struct{}和struct{}{}的区别你知道吗?

struct {}和struct { name string }一样是结构体类型, 只是没有任何元素。struct {}的特点是大小为0,不占用任何内存。比如使用map类型构造集合,可以使用这样一个类型的map:map[string]struct{},使用struct{}类型的值来节省空间。把空行和空格去掉后就是struct {} {},所以到此就可以看出struct {}和struct {} {}的区别了。struct {} {}一个struct {}类型的值,该值也是空。

路多辛的所思所想 1431

比较:C++的struct和class、C和C++的struct

C++中的struct结构体和C语言中的struct结构体差异较大。C++中的struct结构体和C++中的class类极为相似。

han2205277149的博客 3190

Typedef Struct 用法详解

Typedef Struct 用法详解 一、typedef的用法 在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间。 实例像: typedef int INT; typedef int ARRAY[10]; typedef (int*) pINT; typedef可以增强程序的可读性,以及标识符的灵活性...

PengCoX 9937

C 语言中 typedef struct 与 struct 的区别详解

不同系统的可能有不同的长度,使用typedef可以保证代码在不同平台上的一致性。方式适用场景优点缺点struct需要明确结构体标签的情况代码易读,结构清晰需要struct关键字,代码冗长需要简化结构体使用,提高可读性省略struct关键字,代码更简洁可能影响struct命名一致性(匿名结构体)只需定义类型,而不关心struct标签最简洁,减少命名冲突不能使用struct关键字访问在 C 语言编程中,如果你需要提高代码的可读性,避免struct关键字的冗余,推荐使用。如果你需要。

Yhame的博客 1993

Golang struct总结(匿名嵌套及json转struct)

func main() { //json转struct var jsonBlob = []byte(`{"Results":[ {"Name": "Platypus", "Order": "Monotremata","id":111}, {"Name": "Quoll", "Order": "Dasyuromorphia"} ]}`) //struct嵌套stru...

ezreal_pan的博客 4009

[golang]struct {}

有c/c++学习经历的会发现go的struct语法和c/c++很类型,但是golang的struct{}很有意思。 做set,map[string]struct{} 由于struct{}是空,不关心内容,这样map便改造为set chan struct{} 可以做退出 func worker(i int, ch chan Work, quit chan struct{}) { ...

宣的专栏 7386

【xv6学习之番外篇】详解struct Env 与 struct Trapframe

鉴于我们有必要对struct Env和struct Trapframe 这两个用户环境的关键结构体有个细致的了解,这篇博文应运而生。主要借鉴张弛的report。(内联汇编参见 http://grid.hust.edu.cn/zyshao/OSEngineering.htm 第二章) 首先是 Env 结构体: inc/env.h 这其中的 env_tf 存储了各寄存器内容

mick_seu的博客 4744

python中import struct_python学习之struct模块

class struct.Struct(format)返回一个struct对象(结构体,参考C)。该对象可以根据格式化字符串的格式来读写二进制数据。第一个参数(格式化字符串)可以指定字节的顺序。默认是根据系统来确定,也提供自定义的方式,只需要在前面加上特定字符即可:struct.Struct('>I4sf')特定字符对照表附件有。常见方法和属性:方法pack(v1, v2, …)返回一个字节...

weixin_39685836的博客 904
上一篇: C/C++笔试题(3)
下一篇: VC++6.0编译环境介绍
Mr-Chen
博客等级 码龄24年 57粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值