• 指针直接赋值为整型AND利用宏定义求结构体成员偏移量


    首先我们要更正一个很熟悉的概念,那就是指针不仅仅是“地址”,指针还有一个很重要的特性,那就是“类型”

    指针初始化时,“=”的右操作数必须为内存中数据的地址,不可以是变量,也不可以直接用整型地址值(但是 int *p = 0; 除外,该语句表示指针为空);

    所以 int *p = 10; 这样的代码是不允许的。在C++里面直接是error的,即使在一些C编译器中以warning的形式提示,但是warning有的时候也很严重。所以这种东西不要用。从const int到int*是不存在隐士转换的。

    正确的使用方法是 int *p = (int*)10; 这样就先使10这个地址增加一个类型,然后在赋值给int *p。看这句话的汇编:

    00401048   mov         dword ptr [ebp-4],0Ah
    

    就是把10放到p对应的内存空间去。


    这里可以看出可以把一个地址加上一个类型,这样的话就构成了一个指针,但是这个指针类似一个常量,就像10这个立即数默认是int类型,不会产生代码,所以(int*)10也不会产生汇编代码。所以不会出现去访问内存的保护区域这种情况发生。

    那么下面开始说利用宏定义求结构体成员偏移量

    我们在书写C程序的时候,有时候需要根据结构体成员变量的地址,得到结构体的地址,特别是我们想用C来实现C++的继承特性的时候。
    我们对问题的分析如下:

    输入:一个结构体定义type,这个结构体中某个成员变量的名字member以及它的地址ptr
    输出:包含此成员变量的结构体的地址
    

    为了便于分析,我们给出一个实例来说明

    struct father_t {
    int a;
    char *b;
    double c;
    }f;
    char *ptr = &(f.b);
    //而不是 ptr = f.b; 这里ptr是b的地址,而不是它指向的地址。
    根据C语言对struct类型的存储特性,我们可以画这么一个图示:
    

    注意:f.b是一个指针,指向char*b的第一个字符,&(f.b)是这个指针的地址。

    通过分析图示,我们可以看出,我们只需要把当前知道的成员变量的地址ptr,减去它在结构体当中相对偏移量4就的到了结构体的地址(ptr-4)。

    在linux当中对此有一个很好的宏可以使用,叫做 container_of, 放在 linux/kernel.h当中。它的定义如下所示:

    #define offsetof(TYPE, MEMBER) ( (size_t) & ((TYPE *)0)->MEMBER )

    注意:这个宏定义的输入是一个结构体的类型,这个结构体的一个成员变量。

    宏功能:获得一个结构体变量成员在此结构体中的偏移量。
    
    1. ( (TYPE *)0 ) 将零转型为TYPE类型指针;
    2. ((TYPE *)0)->MEMBER 访问结构中的数据成员;
    3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址,即相对于0的偏移量,要的就这个;
    4.(size_t)(&(((TYPE*)0)->MEMBER))结果转换类型,size_t应该最终为unsigned int类型。
    
    此宏的巧妙之处在于将 0 转换成(TYPE*),这样结构体中成员的地址即为在此结构体中的偏移量。
    

    这里只是利用0这个地址,使它具有类型,并没有访问0地址对应的内存空间里的数据,所以不会发生读写保护存储区这种情况。

    #define offset(type, a) ( (unsigned int) &(((type*)0)->a) )
    
    struct _test_
    {
    	int a;
    	char x;
    	double d;
    	char ch[10];
    };
    
    int main()
    {
    	cout << offset(struct _test_, ch) << endl;
    	return 0;
    }
    

    根据结构体内存对齐的方式,得到的结果正好是16。

    参考文章:http://www.cnblogs.com/youxin/p/3348227.html

      

  • 相关阅读:
    洛谷 P1244 青蛙过河
    洛谷 P1004 方格取数
    洛谷 CF894A QAQ
    【题解】洛谷 P5506 封锁
    洛谷 P3884 [JLOI2009]二叉树问题
    Bzoj4894 天赋
    Bzoj4893 项链分赃
    Bzoj3583 杰杰的女性朋友
    POJ3233 Matrix Power Series
    UOJ#204 【APIO2016】Boat
  • 原文地址:https://www.cnblogs.com/stemon/p/4883091.html
Copyright © 2020-2023  润新知