【C/C++】如何利用char型数组buffer存放指针

时间:2021-12-24 23:55:24

由于内存规划限制,某数据结构中不能再增加新的指针,但该结构的char数组型buffer中存在一些可用空间。

于是使用了如下方法保存回调函数指针和链表结构。

先把代码放上来,有时间再补充文字介绍。

#include <iostream>
#include <string>
#include <list>
#include <fstream>
using namespace std;

#define ADD 1
#define SUB 2
#define CALLBACK_PTR_POS 46
#define PREV_PTR_POS 4
#define NEXT_PTR_POS 17

struct Obj
{
int para1;
int para2;
char buf[64];
};


int Add(int para1, int para2)
{
int ret = para1 + para2;
cout << para1 << " + " << para2 << " = " << ret << endl;
return ret;
}

int Sub(int para1, int para2)
{
int ret = para1 - para2;
cout << para1 << " - " << para2 << " = " << ret << endl;
return ret;
}


Obj* CreateObj(int para1, int para2, int type)
{
Obj* pObj = new Obj;
pObj->para1 = para1;
pObj->para2 = para2;
switch(type)
{
case ADD:
*(int(**)(int,int))(&(pObj->buf[CALLBACK_PTR_POS])) = Add;
break;
case SUB:
*(int(**)(int,int))(&(pObj->buf[CALLBACK_PTR_POS])) = Sub;
break;
default:
return NULL;
}
return pObj;
}

int DestroyObj(Obj* pObj)
{
if (NULL == pObj)
return -1;

delete pObj;
return 0;
}

void OperateObj(Obj* pObj)
{
(*(int(**)(int,int))(&(pObj->buf[CALLBACK_PTR_POS])))(pObj->para1, pObj->para2);
}


inline void RegistNeighbor(Obj* front, Obj* back)
{
if (NULL != front)
*(Obj**)(&front->buf[NEXT_PTR_POS]) = back;

if (NULL != back)
*(Obj**)(&back->buf[PREV_PTR_POS]) = front;
}

Obj* startPos = NULL;;

int Init(const string& fileName)
{
ifstream ifs(fileName.c_str());
int para1, para2, op;
Obj* prev = NULL;
Obj* cur = NULL;

while (ifs >> para1 >> para2 >> op && NULL == (cur = CreateObj(para1, para2, op)))
{
/*intentionally left blank*/
}

startPos = cur;
RegistNeighbor(NULL, cur);
prev = cur;

while (ifs >> para1 >> para2 >> op)
{
cur = CreateObj(para1, para2, op);
if (NULL == cur)
continue;
RegistNeighbor(prev, cur);
prev = cur;
}
RegistNeighbor(cur, NULL);
return 0;
}


int Work()
{
Obj* curObj = startPos;
while (NULL != curObj)
{
OperateObj(curObj);
Obj* prevObj = curObj;
curObj = *(Obj**)(&prevObj->buf[NEXT_PTR_POS]);
DestroyObj(prevObj);
}
return 0;
}


int main(int argc, char** argv)
{
Init(argv[1]);

Work();
}