c_cpp 使用地址偏移量包含N个元素的数组成员计算struct的大小
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 使用地址偏移量包含N个元素的数组成员计算struct的大小相关的知识,希望对你有一定的参考价值。
#include <assert.h> // for assert
#include <stdio.h> // for printf
#include <stdlib.h> // for malloc
#define fieldOffset(type, field) ((size_t) &((type *) 0)->field)
#define ContainerPointer(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - fieldOffset(type,member) );})
// No Memory Alignment with GCC
struct Foo {
int a; // 4 bytes
double b[1]; // 8 bytes
} __attribute__((packed));;
typedef struct Foo Foo;
// Memory Alignment with GCC(Non-packed)
// struct Foo {
// int a; // 4 bytes
// double b[1]; // 8 bytes
// }
int main()
{
printf("size of Foo: %lu\n", sizeof(Foo));
// Foo
// +------+ <--- 0
// | a |
// +------+
// | b |
// | |
// +------+
Foo* f = 0;
printf("address of f: %p\n", f);
printf("address of f->a: %p\n", &f->a);
// Foo
// +------+ <--- 0 ^
// | a | | 4
// +------+ <--- 4 v
// | b[0] |
// | |
// +------+
// so &f->b[0] - f = &f->b[0] = 4 = sizeof(a)
printf("address of f->b: %p\n", &f->b);
printf("address of f->b[0]: %p\n", &f->b[0]);
// Foo
// +------+ <--- 0
// | a |
// +------+ <--- 4 ^
// | b[0] | | 8
// | | |
// +------+ <--- 12 v
// | b[1] |
// | |
// +------+
// so &f->b[1] - f = &f->b[1] = 12 = sizeof(a) + 1 * sizeof(b)
printf("address of f->b[1]: %p\n", &f->b[1]);
// Foo
// +------+ <--- 0
// | a |
// +------+ <--- 4
// | b[0] |
// | |
// +------+ <--- 12 ^
// | b[1] | | 8
// | | |
// +------+ <--- 20 v
// | b[2] |
// | |
// +------+
// so &f->b[2] - f = &f->b[2] = 20 = sizeof(a) + 2 * sizeof(b)
printf("address of f->b[2]: %p\n", &f->b[2]);
// In the same way, the sizeof(a) + N * sizeof(b) = &f->b[N], so we can use
// fieldOffset(Foo, b[N]) to allocate an struct Foo with N double elements.
// fieldOffset interprets address 0 as a pointer for struct Foo and use
// the above offset trick to calculate the size of Foo's field,
// 'a' and N numbers of 'b'.
unsigned int N = 5, size = 0;
size = sizeof(Foo) + sizeof(double) * (N-1);
assert(N >=0 && fieldOffset(Foo, b[N]) == size);
printf("Allocate struct Foo with %d double members:\n", N);
Foo* p = (Foo*) calloc(1, fieldOffset(Foo, b[N]));
p->a = N;
unsigned int i = 0;
for (i = 0 ; i < N ; ++i) {
p->b[i] = (double)i;
printf("p->b[%d] = %lf\n", i, p->b[i]);
}
// p->b[N] = 1.0; // Overflow!
for (i = 0 ; i < N ; ++i) {
f = ContainerPointer(&p->b[i], Foo, b[i]);
printf("container of %p is %p\n", &p->b[i], f);
assert(f == p);
}
return 0;
}
以上是关于c_cpp 使用地址偏移量包含N个元素的数组成员计算struct的大小的主要内容,如果未能解决你的问题,请参考以下文章