您的位置:首页 > 编程语言 > C语言/C++

C/C++内存偏移量学习笔记

2012-04-04 20:12 375 查看
  这本来是上学期C++课的课程实验,一直都忘记把它写下来。

  当时的实验要求是用函数模板建立一个函数可以对输入的结构体的任一成员进行函数体的排序。我本身C++学的也比较水,本来说既然确定了结构用个参数把需要进行排序的那一项传进去做个判断,一个成员写一串代码也可以,不过这里正好涉及到了以前学C时一直比较困惑的问题就是怎么对结构体进行动态操作,所以就稍微查了一下。

  当时在网上google了一下,没有找到什么期望中的结果,最后还是在CFAQs里面翻出来了一个偏移量的概念。发现确实是我想要的东西。

  在cstddef这个头文件里本身就有一个offsetof宏可以给我们调用,当然也可以自己定义。这个是CFAQs给出的代码:

#define offsetof(type, f) ((size_t)((char *)&((type *)0)->f - (char *)(type *)0))

这段代码本身是先建立一个type型的0指针(当时正还在这里学习了一下null和0的关系,不过很久不用也基本忘了==b。当时感觉0指针明明不能使用但是却可以分给结构成员空间计算出内存偏移长度特别神奇),然后再指向成员f的内存地址,将f的地址与0指针强制转成char型然后相减就得出来了成员f到结构体头一位内存地址的偏移量,将计算出来的偏移量加到需要操作的结构体的指针上就可以直接得到结构成员的指针。

当时就是从这行代码里我才发现自己一直对宏定义的理解有问题,在我以前的认识里带参宏和函数是十分相似的,->f这种情况应该会建立个局部变量把f值传进来,然后对于一个形参而言这种操作肯定是错误的,不过现在才明白这种带参宏的处理看上去就像是字符串的复制粘贴一样,比想象中强大得多。

在调用原装的offsetof的时候需要注意一个问题,就是结构体中的数据必须是POD型,也就是最早在C语言中定义的定长的数据类型。因为对特定的结构体计算出的长度是固定不变的,如果结构中含有变长的数据就会出现指针错位的情况。按照从网上看到的说法,含有类的结构体是不能计算偏移量的,不过实际使用中在结构中虽然含有String型的成员会有警告,但是实际运行的程序却没有错误,估计是因为在结构体中存储的只是String类的指针。

顺道把当时写的可以对链表进行基于任意成员排序的函数模板贴上来

template<class STRUCT,class ELEMENT>
int insertSort(STRUCT head,ELEMENT type,int offset)
{
STRUCT p,tmp,pTmp;

if(head->next==NULL&&head==NULL)
{
return 0;
}
pTmp = head->next;
head->next = NULL;
p = head;
while(pTmp)
{
while(p->next)
{
//将关键字成员的内存偏移量与链表结点的
//地址相加得到成员的内存地址,强制转型
//后取值进行比较
if(*(ELEMENT*)((char*)p->next+offset)>
*(ELEMENT*)((char*)pTmp+offset))
{
break;
}
p = p->next;
}
tmp = pTmp;
pTmp = pTmp->next;
tmp->next = p->next;
p->next = tmp;
p = head;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: