Skip to content

Instantly share code, notes, and snippets.

@Johniel
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Johniel/9150649 to your computer and use it in GitHub Desktop.
Save Johniel/9150649 to your computer and use it in GitHub Desktop.
container_of怖い
#include <iostream>
#include <vector>
using namespace std;
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define list_entry(ptr, type, member) container_of(ptr, type, member)
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member)* __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
struct List { List* next; };
struct V { int value; List list; };
struct U { char value; List list; };
struct W { long long int value; List list; };
void type_test_W()
{
vector<W*> node_data;
node_data.push_back(new W());
node_data.back()->value = 'A';
for (int size = 10; size--; ) {
W* next = new W();
next->value = node_data.size() + 'A';
node_data.back()->list.next = &(next->list);
node_data.push_back(next);
}
List* head = &(node_data.front()->list);
for (int cnt = 10; cnt--; ) {
W* t = list_entry((void*)head->next, W, list);
cout << ">> " << t->value << endl;
head = &(t->list);
}
return ;
}
void type_test_V()
{
vector<V*> node_data;
node_data.push_back(new V());
node_data.back()->value = 'A';
for (int size = 10; size--; ) {
V* next = new V();
next->value = node_data.size() + 'A';
node_data.back()->list.next = &(next->list);
node_data.push_back(next);
}
List* head = &(node_data.front()->list);
for (int cnt = 10; cnt--; ) {
V* t = list_entry((void*)head->next, V, list);
cout << ">> " << t->value << endl;
head = &(t->list);
}
return ;
}
void type_test_U()
{
vector<U*> node_data;
node_data.push_back(new U());
node_data.back()->value = 'A';
for (int size = 10; size--; ) {
U* next = new U();
next->value = node_data.size() + 'A';
node_data.back()->list.next = &(next->list);
node_data.push_back(next);
}
List* head = &(node_data.front()->list);
for (int cnt = 10; cnt--; ) {
U* t = list_entry((void*)head->next, U, list);
cout << ">> " << t->value << endl;
head = &(t->list);
}
return ;
}
int main(int argc, char *argv[])
{
cout << offsetof(U, value) << endl; // 0
cout << offsetof(U, list) << endl; // 4
cout << endl;
type_test_U();
cout << endl;
type_test_V();
cout << endl;
type_test_W();
cout << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment