【genius_platform软件平台开发】第八十五讲:如何获取结构体数据成员的偏移量(巧妙)
标签: 【genius_platform软件平台开发】第八十五讲:如何获取结构体数据成员的偏移量(巧妙) Python博客 51CTO博客
2023-04-25 18:23:56 229浏览
【genius_platform软件平台开发】第八十五讲:如何获取结构体数据成员的偏移量(巧妙),今天在项目中需要使用到结构体数据成员的偏移量计算,可以使用下面的方法来进行巧妙的获取,注意区别数据成员的赋值操作哦;1.结构体指针为0时,数据成员赋值会内存访问崩溃2.结构体指针为0时,数据成员可以内存访问并计算偏移量源代码:#include"stdafx.h"#ifdefined(BUILD_AMBARELLA_AMBACV_DRV)&&defined(BUI
- 今天在项目中需要使用到结构体数据成员的偏移量计算,可以使用下面的方法来进行巧妙的获取,注意区别数据成员的赋值操作哦;
1. 结构体指针为0时,数据成员赋值会内存访问崩溃

2. 结构体指针为0时,数据成员可以内存访问并计算偏移量
- 源代码:
#include "stdafx.h"
#if defined (BUILD_AMBARELLA_AMBACV_DRV) && defined (BUILD_AMBARELLA_CAVALRY_DRV)
#error "Can not enable ambacv and cavalry at the same time"
#elif defined (BUILD_AMBARELLA_AMBACV_DRV)
#define CAVALRY_DEV_NODE "/dev/ambacv"
#else
#define CAVALRY_DEV_NODE "/dev/cavalry"
#endif
typedef struct
{
int nHasMm2S; /* Has transmit channel */
int nHasS2Mm; /* Has receive channel */
int nInitialized; /* Driver has been initialized */
int nHasSg;
int nTxNumChannels;
int nRxNumChannels;
int nMicroDmaMode;
int nAddrWidth; /**< Address Width */
}stuXAxiDma;
/*****************************************************************************/
/** 1.5 chip common part, audio interface, depend on DMA interface
******************************************************************************/
#define VAROFFSET(type, mem) ((unsigned long)(&((type *)0)->mem))
#define GET_STRUCT_ENTRY(ptr, type, mem) ((type *)((char *)ptr - VAROFFSET(type, mem)))
/*
*callback function
*Check interrupt status and assert s2mm flag
*/
typedef struct
{
int* pBdTxChainBuffer;
int* pBdRxChainBuffer;
int nDmaDevId;
int nS2mmIntrId;
int nMm2sIntrId;
int nBdCount;
char cBdNum; // 注意未对齐32位系统占4个字节
void(*s2mmFinishCb)(void*);
void(*mm2sFinishCb)(void*);
stuXAxiDma axiDma;
}stuChipAudioChannel;
static void dmaInterruptHandler(void* pCallBackRef)
{
// 进行指针转换
stuXAxiDma* pXAxiDmaPtr = (stuXAxiDma *)pCallBackRef;
printf("dmaInterruptHandler::pCallBackRef=[%p]\n", pCallBackRef);
//注意堆的特性,向上生长,地址变小
//stuChipAudioChannel *p_audio_channel = (stuChipAudioChannel *)((char *)ptr - ((int)&((stuChipAudioChannel*)0)->axiDma));
stuChipAudioChannel* pAudioChannel = GET_STRUCT_ENTRY(pCallBackRef, stuChipAudioChannel, axiDma);
printf("dmaInterruptHandler::pAudioChannel=[%p]\n", pAudioChannel);
}
int _tmain(int argc, _TCHAR* argv[])
{
// 申请内存给指针ptr赋值
stuXAxiDma* ptr = new stuXAxiDma();
//指针ptr设置为空((void*)0)
//ptr = NULL;
// 设置指针ptr的数据成员nAddrWidth = 0
ptr->nAddrWidth = 0; // 内存访问会报错
// 只是访问取数据成员变量没问题
int nAddrWidthOffset = (int)&(ptr->nAddrWidth);
// 能够直接取出偏移量来
int nBdTxChainBufferOffset = ((int)(&((stuChipAudioChannel*)0)->pBdTxChainBuffer));
// nBdTxChainBufferOffset=0
printf("_tmain::nBdTxChainBufferOffset=[%d]\n", nBdTxChainBufferOffset);
int nDmaDevIdOffset = ((int)(&((stuChipAudioChannel*)0)->nDmaDevId));
printf("_tmain::nDmaDevIdOffset=[%d]\n", nDmaDevIdOffset);
int nS2mmFinishCbOffset = ((int)(&((stuChipAudioChannel*)0)->s2mmFinishCb));
printf("_tmain::nS2mmFinishCbOffset=[%d]\n", nS2mmFinishCbOffset);
int nAxiDmaOffset = ((int)(&((stuChipAudioChannel*)0)->axiDma));
printf("_tmain::nAxiDmaOffset=[%d]\n", nAxiDmaOffset);
// 申请堆内存给pXAxiDma变量
stuXAxiDma* pXAxiDma = new stuXAxiDma;
dmaInterruptHandler(pXAxiDma);
return 0;
}
- 输出结果:
3. 原理解释:
- 在结构体成员变量前面加上取地址符号&后表示取的是
nAddrWidth字段的地址,而不是引用该字段内容,因此不会产生段错误。 - 如果
ptr为空,直接取该成员变量的内容或者更新、设置该内存的值时会发生段错误。
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
暂无评论,快来写一下吧
展开评论


