offsetof(s,m)解析
https://www.cnblogs.com/jingzhishen/p/3696293.html
sizeof()用法汇总
sizeof()功能:计算数据空间的字节数
1.与strlen()比较
strlen()计算字符数组的字符数,以"\0"为结束判断,不计算为'\0'的数组元素。
而sizeof计算数据(包括数组、变量、类型、结构体等)所占内存空间,用字节数表示。
2.指针与静态数组的sizeof操作
指针均可看为变量类型的一种。所有指针变量的sizeof 操作结果均为4。
注意:int *p; sizeof(p)=4;
但sizeof(*p)相当于sizeof(int);
对于静态数组,sizeof可直接计算数组大小;
例:int a[10];char b[]="hello";
sizeof(a)等于4*10=40;
sizeof(b)等于6;
注意:数组做型参时,数组名称当作指针使用!!
void fun(char p[])
{sizeof(p)等于4}
char str[20]="0123456789";
int a=strlen(str); //a=10;
int b=sizeof(str); //而b=20;
char ss[] = "0123456789";
sizeof(ss) 结果 11 ===》ss是数组,计算到\0位置,因此是10+1
sizeof(*ss) 结果 1 ===》*ss是第一个字符
char ss[100] = "0123456789";
sizeof(ss) 结果是100 ===》ss表示在内存中的大小 100×1
strlen(ss) 结果是10 ===》strlen是个函数内部实现是用一个循环计算到\0为止之前
int ss[100] = "0123456789";
sizeof(ss) 结果 400 ===》ss表示在内存中的大小 100×4
strlen(ss) 错误 ===》strlen的参数只能是char* 且必须是以'\0'结尾的
char q[]="abc";
char p[]="a\n";
sizeof(q),sizeof(p),strlen(q),strlen(p); 结果是 4 3 3 2
一些朋友刚开始时把sizeof当作了求数组元素的个数,如今你应该知道这是不对的,那么应该怎么求数组元素的个数呢Easy,通常有下面两种写法:
1.int c1 = sizeof( a1 ) / sizeof( char ); // 总长度/单个元素的长度
2.int c2 = sizeof( a1 ) / sizeof( a1[0] ); // 总长度/第一个元素的长度
Student stus[4]={
{"humingtao",24,99},
{"zhaoweisong",23,66},
{"chenfengchang",21,88},
{"zhuwenpeng",20,77}
数组长度 count = sizeof(stus)/sizeof(stus[0]
double* (*a)[3][6];
cout<<sizeof(a)<<endl; // 4 a为指针
cout<<sizeof(*a)<<endl; // 72 *a为一个有3*6个指针元素的数组
cout<<sizeof(**a)<<endl; // 24 **a为数组一维的6个指针
cout<<sizeof(***a)<<endl; // 4 ***a为一维的第一个指针
cout<<sizeof(****a)<<endl; // 8 ****a为一个double变量
offsetof(s,m)解析
const AVClass *class;
char *expr_str;
AVExpr *expr;
double var_values[VAR_VARS_NB];
enum AVMediaType type;
} SetPTSContext;
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
static const AVOption options[] = {
{ "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = FLAGS },
{ NULL }
};
&((s *)0)->m 是要取得类s中成员变量m的地址
由于这个类(或结构)的基址为0,这时m的地址当然就是m在s中的偏移了
我们许多人可能都使用过一些非挥发性的存储器,如常见的EEPROM。我们经常使用它们在存储一些系统的配置参数和设备信息。在所有的EEPROM中,通过串口访问的占了大多数。一般来说,对串口的访问都是按字节进行的,这使得我们不可避免会设计出下面的
接口去访问EEPROM的信息:
ee_rd(uint16_t offset, uint16_t nBytes, uint8_t * dest);
定义一个数据结构和一个指向这个数据结构的指针,并初始化这个指针为EEPROM的起始地址EEPROM_BASE.
| i | f | c | | | |...
----------------------------
| | | | | | |...
----------------------------
| | | | | | |...
----------------------------
...
----------------------------
{
int i;
float f;
char c;
} EEPROM;
a.容易使代码维护人员人误以为在ee_rd接口内部也存在EEPROM的数据结构。
b.当你编写一些自己感觉良好编译器不报错的代码,比如pEE->f = 3.2,你可能意想不到灾难将要来临。
c.这个接口没有很好地体现EEPROM所隐含的硬件特性。
比如成员f在EEPROM数据结构中的偏移量,这里为什么
要强制转化0,这是个有深度的问题,在后面也会详细说明*/
#define offsetof(type, f) ((size_t) \
((char *)&((type *)0)->f - (char *)(type *)0))
{
int i;
float f;
char c;
} EEPROM;
#define SIZEOF(s,m) ((size_t) sizeof(((s *)0)->m))
{
char pad[EEPROM_BASE];/*使数据结构的前EEPROM_BASE个字节填"空"*/
int i;
float f;
char c;
} EEPROM;
| | | | | | |...
----------------------------
...
---------------------------- <-EPPROM_BASE:0x00000a10
| i | f | c | | | |...
----------------------------
| | | | | | |...
----------------------------
...
这种映射使原本复杂的寄存器访问变得象访问普通的RAM地址一样方便。
在我们视频会议系统中,PowerPC 8250访问外部的ROM控制器(ROM controller)的
寄 存器就是通过这种方式实现的。ROM控制器所有的寄存器被映射到从I/O寄存器空间基地址0x10000000(IO_BASE)偏移 0x60000(ROMCONOffset)字节的一段内存。每个寄存器占用四个字节,并有一个数据结构与它们对应。比如控制ROM控制器工作状态的寄存 器对应数据结构ROMCON_ROM_CONTROL,配置PCI总线A的寄存器对应数据结构ROMCON_CONFIG_A,下面先看看这些数据结构的定义:
union {
struct {
UINT32 pad4:21; /* unused */
UINT32 pad3:2; /* reserved */
UINT32 pad2:5; /* unused */
UINT32 EnablePCIA:1;
UINT32 pad1:1; /* reserved */
UINT32 EnableBoot:1;
UINT32 EnableCpu:1; /*bit to enable cpu*/
} nlstruct;
UINT32 ConfigA;
} nlstruct4;
} nlunion;
} ROMCON_CONFIG_A, *PROMCON_CONFIG_A;
union {
struct {
UINT32 TransferComplete:1;
UINT32 pad3:1; /* unused */
UINT32 BondPad3To2:2;
UINT32 Advance:3;
UINT32 VersaPortDisable:1;
UINT32 pad2:1; /* unused */
UINT32 FastClks:1;
UINT32 pad1:7; /* unused */
UINT32 CsToFinClks:2;
UINT32 OeToCsClks:2;
UINT32 DataToOeClks:2;
UINT32 OeToDataClks:3;
UINT32 CsToOeClks:2;
UINT32 AddrToCsClks:2;
UINT32 AleWidth:2;
} nlstruct;
UINT32 RomControl;
} nlstruct4;
} nlunion;
} ROMCON_ROM_CONTROL, *PROMCON_ROM_CONTROL;
{
ROMCON_CONFIG_A ConfigA;
ROMCON_CONFIG_B ConfigB;
ROMCON_ROM_CONTROL RomControl;
...
}ROMCON, *PROMCON;
| | | | | | |...
----------------------------
| | | | | | |...
...
---------------------------- <-ROMCONOffset(ROMCON):0x60000
| | | | | | |...
---------------------------- <-ROMCON_ROM_CONTROL
...
----------------------------
估计有人可能会这样做:
事先定义成员RomControl(ROMCON中用ROMCON_ROM_CONTROL定义的实例)相对与ROMCON的偏移量,
void rom_write(dword_t* src, uint32_t* dest);
if(!tRomCtrl.nlunion.nlstruct.VersaPortDisable)
{
tRomCtrl.nlunion.nlstruct.VersaPortDisable = 1;
}
这样做确实可以达到访问相应寄存器的目的。但是,如果和ROM相关的寄存器很多,那么定义、记忆和管理那么多偏移量不是很不方便吗?到这里,如果你对前面关于offsetof还有印象的话,我想你可能会作下面的优化:
#define ROMCON_ADDR(m) (((size_t)IO_BASE+\
(size_t)ROMCONOffset+\
(size_t)offsetof(ROMCON,m))
dword_t* pReg=(dword_t*)ROMCON_ADDR(ConfigA);
if(!tRomCtrl.nlunion.nlstruct.VersaPortDisable)
{
tRomCtrl.nlunion.nlstruct.VersaPortDisable = 1;
}
通过前面的举例,你可能对如何使用offsetof已经不陌生了吧。offsetof对那些搞
C++ 的人可能很熟悉,因为offsetof类似于sizeof,也是一种系统操作符,你不用考虑它是怎么定义的。这个操作符offsetof的定义可以在 ANSI C 编译器所带的stddef.h中找到。在嵌入式系统里,不同开发商,不同架构处理器和编译器都有不同的offsetof定义形式:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#define offsetof(s,m) (size_t)(unsigned long)&(((s *)0)->m)
#define offsetof(s,memb) ((size_t)((char *)&((s *)0)->memb-(char *)0))
#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
((s *)0):强制转化成数据结构指针,并使其指向地址0;
((s *)0)->m:使该指针指向成员m
&(((s *)0)->m):获取该成员m的地址
(size_t)&(((s *)0)->m):转化这个地址为合适的类型
{
unsigned int a:3;
unsigned int b:13;
unsigned int c:16;
}foo;
offsetof(s,m)解析的更多相关文章
- 结构体指offsetof宏详细解析
1.#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER) (include/linux/stddef.h) ...
- Nginx的client_header_buffer_size和large_client_header_buffers学习
之前看到有人写的一篇关于nginx配置中large_client_header_buffers的问题排查的文章,其中提到: large_client_header_buffers 虽然也可以在serv ...
- 【C/C++编程入门学习】C语言结构体硬核玩法分享,一切皆是数据!
前言 对于结构体的应用太多了,今天这篇文章我主要为大家总结平时关于结构体的一些独特硬核小技巧,对于结构体更多优秀的编程表现,如果你对结构体的基础知识还不具备的话得回头看一下专栏教程或者自己找本书籍学习 ...
- Python2 基本数据结构源码解析
Python2 基本数据结构源码解析 Contents 0x00. Preface 0x01. PyObject 0x01. PyIntObject 0x02. PyFloatObject 0x04. ...
- Nginx学习之二-配置项解析及编程实现
在开发功能灵活的Nginx模块时,需要从配置文件中获取特定的信息.不过,我们并不需要再编写一套读取配置的系统,Nginx已经为用户提供了强大的配置项解析机制,同时还支持“-s reload”命令,可以 ...
- Nginx学习——http配置项解析编程
http配置项解析编程 配置config ngx_addon_name=ngx_http_mytest_module HTTP_MODULES="$HTTP_MODULES ngx_http ...
- nginx源代码分析--配置文件解析
ngx-conf-parsing 对 Nginx 配置文件的一些认识: 配置指令具有作用域,分为全局作用域和使用 {} 创建其他作用域. 同一作用域的不同的配置指令没有先后顺序:同一作用域能否使用同样 ...
- typeof, offsetof 和container_of
要理解Linux中实现的双向循环链表("侵入式"链表),首先得弄明白宏container_of. 本文尝试从gcc的关键字typeof和宏offsetof入手,循序渐进地剖析宏co ...
- C语言之浅析网络包解析
1.这几天研究skynet中的 lua-netpack.c 中的解析数据包过程.于是把lua部分去掉,修改了一些接口,留下解包相关的代码.再结合云风写的网络代码的例子, 写了一个最简单形式的客户端封包 ...
随机推荐
- Spring Cloud Alibaba与Spring Boot、Spring Cloud之间不得不说的版本关系
这篇博文是临时增加出来的内容,主要是由于最近连载<Spring Cloud Alibaba基础教程>系列的时候,碰到读者咨询的大量问题中存在一个比较普遍的问题:版本的选择.其实这类问题,在 ...
- (摘)sql-索引的作用(超详细)
(一)深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录.微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonc ...
- C#杂记-自动实现的属性(自动属性)
基础知识: 普通属性:可读或可写并将值存储到一个私有变量中的属性,不对数据做任何加工,没有自定义代码. private string name public string Name { get{ret ...
- [日常] Go-逐行读取文本信息
go逐行读取文本信息:1.os包提供了操作系统函数的不依赖平台的接口,Open方法打开一个文件用于读取,func Open(name string) (file *File, err error)2. ...
- 一文读懂HTTP/2及HTTP/3特性
摘要: 学习 HTTP/2 与 HTTP/3. 前言 HTTP/2 相比于 HTTP/1,可以说是大幅度提高了网页的性能,只需要升级到该协议就可以减少很多之前需要做的性能优化工作,当然兼容问题以及如何 ...
- 原生js获取元素非行内样式属性的方法
获取当前对象的样式DOM标准中的全局方法 getComputedStyle(obj).width (获取元素的宽度),但在非标准IE浏览器(IE8)以下有兼容问题IE8以下要这样写 obj.curre ...
- SAP QA32 做使用决策系统报错:分类数据的不一致性=>交易终止
SAP QA32 做使用决策系统报错:分类数据的不一致性=>交易终止 QA32,对如下检验批做处理,系统报错, 试图使用MSC3N去显示这个批次主数据,同样报错, 原因在于批次的分类数据产生后, ...
- ABP大型项目实战(1) - 目录
前面我写了<如何用ABP框架快速完成项目>系列文章,讲述了如何用ABP快速完成项目. 然后我收到很多反馈,其中一个被经常问到的问题就是,“看了你的课程,发现ABP的优势是快速开发,那么 ...
- Linux系统性能分析工具 sar--系统活动情况报告
1.结论: sar 命令是linux系统上,分析系统性能的常用工具,可以查看cpu.内存.磁盘IO.文件读写.系统调用, 2.sar会有一个定时任务,定期记录当前系统信息到 /var/log/sa/ ...
- 实现MongoDB读写分离的“读偏好”介绍
在某些情况下,将读请求发送给副本集的备份节点是合理的,例如,单个服务器无法处理应用的读压力,就可以把查询请求路由到可复制集中的多台服务器上.现在绝大部分MongoDB驱动支持读偏好设置(read pr ...