note of Linux 核心原始程式碼巨集: container_of
在 linux source code 裡被 referenced 巨多次
https://elixir.bootlin.com/linux/latest/A/ident/container_of
struct data {
short a;
char b;
double c;
};
#include <stdio.h>
struct data {
short a;
char b;
double c;
};
int main() {
struct data x = {.a = 25, .b = 'A', .c = 12.45};
char *p = (char *) &x;
printf("a=%d\n", *((short *) p)); //a=25
p += sizeof(short);
printf("b=%c\n", *((char *) p));//b=A
p += sizeof(char);
printf("c=%lf\n", *((double *) p));//c=c=190346578175708908992881173523240944319242933565425065476600793027569625765132922491647361749301545251588213454633589801374830370131288956923386722390475742252870531685634044870495567872.000000.
return 0;
}
指標操作前須轉型為 (char*) 做加減才會 shift 1 byte.
printf("p=%p, &x.c=%p\n", p, &(x.c));
//p=0x16dad74a3
//&x.c=0x16dad74a8
why?
data-alignment
需改成
struct data {
short a;
char b;
double c;
} __attribute__((packed));;
但就會有效能疑慮
How to get correct pointer?
用 offsetof
用法:
p = (char *) &x + offsetof(struct data, c);
#define offsetof(st, m) \
((size_t)((char *)&((st *)0)->m - (char *)0))
offsetof(struct data, c)
would be (use gcc -E to expand macro)
((size_t)((char *)&((struct data *)0)->c - (char *)0));
container_of 就是把藉由 struct 與 data 本身的關係,藉由 data 的指標,得到 struct 的指標
我爸的指標 = container_of(我的指標, 爸爸, 兒子)
typedef struct { int ref; } Object;
typedef struct { Object base; /* Vehicle-specific members */ } Vehicle;
typedef struct { Vehicle base; /* Car-specific members */ } Car;
// Car 繼承了 Vehicle
void vehicleStart(Vehicle *obj) {
if (obj) printf("%x derived from %x\n", obj, obj->base);
}
int main(void) {
Car c;
vehicleStart((Vehicle *) &c);
}
例子
imx214.c
/* container_of() - Calculate address of object that contains address ptr
* @ptr: pointer to member variable
* @type: type of the structure containing ptr
* @member: name of the member variable in struct @type
*
* Return: @type pointer of object containing ptr
*/
#define container_of(ptr, type, member) \
__extension__({ \
const __typeof__(((type *) 0)->member) *(__pmember) = (ptr); \
(type *) ((char *) __pmember - offsetof(type, member)); \
})
char *parent = __extension__\
({ const __typeof__(((struct data *) 0)->c) *(__pmember)
= (p); \
(struct data *) ((char *) __pmember - offsetof(struct data, c)); });
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up