作者VictorTom (鬼翼&娃娃魚)
看板C_and_CPP
標題Re: [問題] ((TYPE *) 0)-> .... 代表的是??
時間Tue Jul 20 01:27:48 2010
※ 引述《leontsai (幻風)》之銘言:
: 有沒有高手請教一下我的疑惑
: 感恩
: 這MACRO 最主要是要回傳This 指標的PRIVATE 資料
: 其中
: Record 為一指標 BBS_PROTOCOL * This
: TYPE 為一結構
: Field 為結構TYPE 中一個 component
: #define _CR(Record, TYPE, Field) \
: ((TYPE *) ( (CHAR8 *)(Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
: 1.最不能理解的是 0 ((TYPE *) 0) 這結構0代表是神麼意思?
: 2. &(((TYPE *) 0)->Field))) 轉型為 (CHAR8 *) ? 位址轉型為 指向 CHAR8 的指標
抱歉回了這麼久以前的文, 小弟最近在一個偶然的機會....
又看到了這個三年前面試被問過的題目, 本想po文請教....
沒想到板上已經有文章了, 那就回在同一個標題下面吧....
憑印象記的macro, 加自己湊的範例, code不長直接貼吧@@"
==
#include <stdio.h>
#include <stdlib.h>
#define OFFSET(type, element) ( &(((type*)0)->element) )
typedef struct _TESTrec
{
int x, y;
char str[10];
double z;
int dummy[2];
} TEST;
int main()
{
printf("sizeof(TEST) = 0x%08X\n", sizeof(TEST));
printf("offset of str = 0x%p\n",
OFFSET(TEST, str));
printf("offset of z = 0x%p\n",
OFFSET(TEST, z));
system("PAUSE");
return 0;
}
==
主要是OFFSET這個macro裡這段: ((type*)0)->element
以前老迷惑於"對0轉型成指標存取element為什麼不會access violation"??
然後又取址, 或者像l大看到的組合了一堆奇怪的位址運算到底是算什麼?_?
剛剛憑印象生出上面的code以後, 大概有了如下的推論
OFFSET(TEST, str) 展開以後 ( &(((TEST*)0)->str) )
如果把 0 (零) 假設當成TEST* O (大o) 來看好了....
這段code可寫成 &(O->str), 如果O指到0x0010000....
那麼O->str指0x00100008, O->z指0x00100018(有align)
接著如果O指到0x00000000呢??就跟macro一模一樣了....
那麼O->str指0x00000008, O->z指0x00000018(有align)
所以OFFSET在上例算出0x00000008與0x00000018兩位址!
也就是說它只是拿來找element在type裡的offset而已Orz
--
藉這篇文悼念一下被&(type*)0->element嚇傻的日子-_-||
PS. 以上數值舉例是假設在sizeof(int)為32的環境下....
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.132.174.98
※ 編輯: VictorTom 來自: 220.132.174.98 (07/20 01:35)
推 loveme00835: V大 拍拍~ 07/20 01:47
推 saxontai:C Standard Library 有提供 offsetof marcro。 07/20 11:09
→ VictorTom:感謝樓上s大的文章....<(_ _)> 07/20 11:18
→ VictorTom:也推一下 #18xm_p1G g大寫的解釋....:) 07/20 11:28
推 godman362:我有疑問,關於g大的return &(ptr->c) 為什麼不會有問題 07/20 14:37
→ godman362:ptr不是擺明指向NULL了嗎?這樣return &(ptr->c)的位址 07/20 14:37
→ godman362:不會有問題產生嗎...? 07/20 14:38
→ godman362:呃抱歉,我沒注意到V大也有解釋 07/20 14:39
→ tinlans:這個 code 之所以能動作是因為標準賦予 & 了特殊的規則。 07/20 15:36
→ tinlans:所以把那一行拆成兩行寫雖然看似等價,但拆開會死。 07/20 15:36
→ tinlans:不過,好像也沒有拆開寫的方法就是了... 07/20 15:39
→ tinlans:同樣的 &(((struct T *)0)[1]) 也是有保證不會真的去做 07/20 15:43
→ tinlans:dereference,會直接代換成加法運算。 07/20 15:43
→ VictorTom:感謝t大的說明....<(_ _)> 07/20 16:59