#define container_of(ptr, type, member) (type*)((char*)ptr-(unsigned long)&((type*)0)->member)
: unsinged long 은 64비트 포인터가 8바이트이기 때문에 이것까지 커버할 수 있어야 함.
해당 타입 포인터가 가리키고 있는 멤버를 4비트 양수로 캐스팅을 하고
1바이트 크기의 캐릭터 변수로 캐스팅을 하고, 그것을 빼면 해당 멤버를 가리키는 메모리 주소가 나옴
그것을 다시 형변환하는 것임. 끝.
SAWON *s ;
s= (SAWON*)((char*)temp - 20); // 패딩이 있기 때문에 이렇게 빼면 안됨.
s = (SAWON*) ((char*)temp - (sizeof(SAWON)-sizeof(NODE)));
for (temp = head->next; temp != head; temp = temp->next)
{
s = container_of(temp, SAWON, list2);
printf("<->[%s]", s->name);
}
temp가 다음 사원의 두번째 노드를 가리킴 따라서.
SAWON 에서 list2를 가리키는 만큼을 빼면 나옴.
아. 원하는 오프셋을 찾는 매크로임. 이것을 제너럴 하게 만들기 위해서, 이렇게 고려해서 만드는 것임.
#define container_of(ptr, type, member) (type*)((char*)ptr-(unsigned long)&((type*)0)->member)
#define container_of(ptr, type, member) (type*)((char*)ptr-(unsigned long)&((type*)0)->member)
//-----------------------------------------
typedef struct {
int a;
int b;
int c;
} AAA;
int main()
{
AAA aaa = { 1,2,3 };
int* temp = &aaa.c;
AAA* p;
p = (AAA*)((char*)temp - (unsigned long)&((AAA*)0)->c);
printf("%d %d %d", p->a, p->b, p->c);
return 0;
}
기존 매크로
#define container_of(ptr, type, member) ((type*)((char*)ptr-(unsigned long)&((type*)0)->member)) 매크로니 마지막에 괄호까지 신공발휘. 일단 이게 해당 구조체가 어떤 구조로 이루어져있는지 모를때. 그리고 제네릭 하게 만들기 위해서 아래 포인터나 왔다갔다 하는 것은 자유롭게 만들고 그 위에 쌓는 데이터가 어떻게 사용되는지 사용자에게 자유도를 주기 위해서 이렇게 작성하는 것임.
macro는 cosnt 키워드를 사용할 수 없음. 매크로의 한계임. 그래서 const typeof(*(x)) *__x = x; 이렇게 read-only data로 만들 수 있음. typeof 는 최신 c 에서 지원하는 내장 함수임.
두 줄 이상의 매크로를 do { 10; 20; }while(0) 으로 하는 것이 관례임. 단 리턴값을 할 수 없음. 소괄호를 쓰면 괜찮음. 그럼 return 도 할 수 있음.
'Computer Science' 카테고리의 다른 글
Generic Hash 2 (0) | 2021.04.29 |
---|---|
Generic Hash 타입 설계 (0) | 2021.04.29 |
최신 매크로 분석 container_of (0) | 2021.04.29 |
타입의 의존성 제거(container_of 버전) (0) | 2021.04.28 |
Generic swap (0) | 2021.04.24 |
댓글