通过成员变量地址获取结构体地址
2014-10-09 14:01
537 查看
Linux中有一个宏
[cpp] view
plaincopyprint?
#define container_of(ptr,type,member) 实现略
实现了通过成员变量地址获取结构体地址的功能。
今天我想好好想想这个实现的原理是怎么来的。
先定义一个结构体吧
[cpp] view
plaincopyprint?
typedef struct
{
int a;
int b;
int c;
}ABC;
再来设计一个函数用来实现功能
[cpp] view
plaincopyprint?
int main(void)
{
ABC abc;
printf("abc : %p\n",&(abc));
printf("abc.c : %p\n",&(abc.c));
return 0;
}
main()刚刚好,嘿嘿
输出结果为
[cpp] view
plaincopyprint?
abc : 0022FF44
abc.c : 0022FF4C
因为成员c的地址比abc高,所以按照数学公式:差 = 成员C地址 - abc地址
如何求得这个差呢?
可以这样,把ABC的一个实例映射到0这个地址,这样成员c的地址就是在0的基础上网上加,进而此时成员c的地址
就是它们的差值
这样
[cpp] view
plaincopyprint?
printf("%u\n",&(((ABC*)0)->c));
不过编译,运行后会crash掉,因为0这个地址被printf检测到是非法地址,所以得这样
[cpp] view
plaincopyprint?
printf("%u\n",(size_t)&(((ABC*)0)->c));
这样,传给printf的参数不是一个地址,而是一个普通的常数
好,那么可以求abc地址了
[cpp] view
plaincopyprint?
printf("%p\n",&(abc.c) - (size_t)&(((ABC*)0)->c));
运行,结果是
[cpp] view
plaincopyprint?
abc : 0022FF2C
和abc的地址不对啊,为什么呢?
因为此处&(abc.c)这一句有问题。指针的加减操作的步长是按照这个指针的类型来定的,此处c是int型,则它 - 8,其实地址是 - 8 * sizeof(int).
你看,0022FF2C是不是比0022FF44少24.就是因为它上面的操作多减了24
所以,得这样
[cpp] view
plaincopyprint?
printf("abc : %p\n",(unsigned char*)&(abc.c) - (size_t)&(((ABC*)0)->c));
输出结果为
[cpp] view
plaincopyprint?
abc : 0022FF44
OK,目标达成。
现在用宏封装一下
[cpp] view
plaincopyprint?
#define container_in(ptr,TYPE,member) \
(TYPE*)((unsigned char*)(ptr) - (size_t)&(((TYPE*)0)->member))
把差值强制转换为(TYPE*)是因为这个宏的目的就是返回(TYPE*)类型的指针
做个测试
[cpp] view
plaincopyprint?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define container_in(ptr,TYPE,member) \
(TYPE*)((unsigned char*)(ptr) - (size_t)&(((TYPE*)0)->member))
typedef struct
{
char a;
char b;
char c;
}TEST1;;
typedef struct
{
char a;
char b;
}TEST2;;
typedef struct
{
char a;
TEST1 test1;
short b;
TEST2 test2;
int c;
}ABC;
int main(void)
{
ABC abc;
ABC* p = NULL;
abc.a = 1;
abc.b = 2;
abc.c = 4;
p = container_in(&(abc.c),ABC,c);
printf("%u %u %u\n",p->a,p->b,p->c);
return 0;
}
输出结果
[cpp] view
plaincopyprint?
1 2 4
原文地址:http://blog.csdn.net/ma52103231/article/details/20036705
[cpp] view
plaincopyprint?
#define container_of(ptr,type,member) 实现略
实现了通过成员变量地址获取结构体地址的功能。
今天我想好好想想这个实现的原理是怎么来的。
先定义一个结构体吧
[cpp] view
plaincopyprint?
typedef struct
{
int a;
int b;
int c;
}ABC;
再来设计一个函数用来实现功能
[cpp] view
plaincopyprint?
int main(void)
{
ABC abc;
printf("abc : %p\n",&(abc));
printf("abc.c : %p\n",&(abc.c));
return 0;
}
main()刚刚好,嘿嘿
输出结果为
[cpp] view
plaincopyprint?
abc : 0022FF44
abc.c : 0022FF4C
因为成员c的地址比abc高,所以按照数学公式:差 = 成员C地址 - abc地址
如何求得这个差呢?
可以这样,把ABC的一个实例映射到0这个地址,这样成员c的地址就是在0的基础上网上加,进而此时成员c的地址
就是它们的差值
这样
[cpp] view
plaincopyprint?
printf("%u\n",&(((ABC*)0)->c));
不过编译,运行后会crash掉,因为0这个地址被printf检测到是非法地址,所以得这样
[cpp] view
plaincopyprint?
printf("%u\n",(size_t)&(((ABC*)0)->c));
这样,传给printf的参数不是一个地址,而是一个普通的常数
好,那么可以求abc地址了
[cpp] view
plaincopyprint?
printf("%p\n",&(abc.c) - (size_t)&(((ABC*)0)->c));
运行,结果是
[cpp] view
plaincopyprint?
abc : 0022FF2C
和abc的地址不对啊,为什么呢?
因为此处&(abc.c)这一句有问题。指针的加减操作的步长是按照这个指针的类型来定的,此处c是int型,则它 - 8,其实地址是 - 8 * sizeof(int).
你看,0022FF2C是不是比0022FF44少24.就是因为它上面的操作多减了24
所以,得这样
[cpp] view
plaincopyprint?
printf("abc : %p\n",(unsigned char*)&(abc.c) - (size_t)&(((ABC*)0)->c));
输出结果为
[cpp] view
plaincopyprint?
abc : 0022FF44
OK,目标达成。
现在用宏封装一下
[cpp] view
plaincopyprint?
#define container_in(ptr,TYPE,member) \
(TYPE*)((unsigned char*)(ptr) - (size_t)&(((TYPE*)0)->member))
把差值强制转换为(TYPE*)是因为这个宏的目的就是返回(TYPE*)类型的指针
做个测试
[cpp] view
plaincopyprint?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define container_in(ptr,TYPE,member) \
(TYPE*)((unsigned char*)(ptr) - (size_t)&(((TYPE*)0)->member))
typedef struct
{
char a;
char b;
char c;
}TEST1;;
typedef struct
{
char a;
char b;
}TEST2;;
typedef struct
{
char a;
TEST1 test1;
short b;
TEST2 test2;
int c;
}ABC;
int main(void)
{
ABC abc;
ABC* p = NULL;
abc.a = 1;
abc.b = 2;
abc.c = 4;
p = container_in(&(abc.c),ABC,c);
printf("%u %u %u\n",p->a,p->b,p->c);
return 0;
}
输出结果
[cpp] view
plaincopyprint?
1 2 4
原文地址:http://blog.csdn.net/ma52103231/article/details/20036705
相关文章推荐
- 通过成员变量地址获取结构体地址
- C语言--通过结构体成员的地址获取结构体变量的地址
- 如何通过结构中的某个成员地址获取结构本身的指针???
- 通过结构体成员的地址获取结构体变量的地址
- 如何通过结构体成员的地址获取结构体变量的地址?
- 通过结构体成员的地址获取结构体变量的地址
- 与struct相关的宏定义 --- 根据成员变量偏移,获取struct起始地址
- 通过结构体成员变量地址得到结构体的地址
- 通过反射获取构造方法,成员变量及成员方法
- 通过反射获取成员变量并使用
- 如何通过一个结构体成员变量的地址找到该结构体的首地址
- C/C++—— 除了用类成员函数访问类私有成员变量外,还可以通过类对象地址来直接访问和修改类的私有成员变量
- 通过结构成员获得结构地址的例子
- 反射:通过反射获取成员变量并使用
- 反射_通过反射获取成员变量并使用
- 根据结构体某一成员的地址得到该结构体变量的首地址
- container_of()如何通过结构中的某个变量获取结构本身的指针???
- 通过操作地址的方法来访问C++类对象中私有成员变量
- Android(java)学习笔记109:通过反射获取成员变量和成员方法并且使用
- Java(通过反射获取成员变量并使用)