2011-05-20 184 views
1

我有一個指向結構的指針,我想通過試驗和錯誤獲取其所有成員。我試圖通過將指針遞增1並去除它來運行結構。它應該從結構中返回一個正確的值(每i*sizeof(int)時間),但它不會。運行結構並打印所有值?

我在做什麼錯?

fn (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) 
{ 

    /* 
    assume that all struct members are int types 

    typedef struct 
    { 
    mach_msg_bits_t msgh_bits; 
    mach_msg_size_t msgh_size; 
    mach_port_t  msgh_remote_port; 
    mach_port_t  msgh_local_port; 
    mach_msg_size_t msgh_reserved; 
    mach_msg_id_t  msgh_id; 
    } mach_msg_header_t; 

    size of the struct is 24. 
    */ 

    printf("ID: %d \n",InHeadP->msgh_id); //prints 'ID: 1337' 
    printf("Ptr: %p\n",InHeadP); 

    for (int i = 0; i <= 24; i++) 
    { 
     int deref = *((int*)(InHeadP+i)); 
     printf("InHeadP[%d]=%d\n",i,deref); 
      //no sign of 1337 anywhere 

    } 
} 

P.S.我知道我不應該那樣做,但這只是爲了測試目的。

+0

'INT * deref'?你不是指'int deref'嗎? – nmichaels 2011-05-20 15:41:19

+0

是的。 'int deref = *((int *)(InHeadP + i))'。改變了它。 – 2011-05-20 15:41:45

+0

「它應該從結構中返回一個正確的值(每個I * sizeof(int)時間),但它不會。」 - 呃爲什麼要這樣?這不完全是如何分配內存。 – zellio 2011-05-20 15:42:32

回答

5

因爲InHeadPmach_msg_header_t*,加入到一個整數實際上添加的整數倍sizeof(mach_msg_header_t),好像你索引mach_msg_header_t秒的陣列(實際上是數組索引是如何工作的)。你需要投InHeadPint*進行運算就可以了,即使如此,與結構有六個領域,i應該只上升到6,不要24

+0

因爲我們幾乎同時在這個問題上聚合!我給這+1,因爲他是正確的我需要去6,而不是24. – andrewdski 2011-05-20 15:51:07

+1

'*(((int *)(InHeadP))+ i)'工作!謝謝! – 2011-05-20 15:51:28

+0

偉大的問題和非常有幫助的答案。謝謝! – 2014-03-09 17:48:58

1

不,你不應該做這個!

什麼特別錯在這裏

for (int i = 0; i <= 24; i++) 
{ 
    int deref = *((int*)(InHeadP+i)); 
    printf("InHeadP[%d]=%d\n",i,deref); 
} 

是你打印的24層不同結構的第一個int值。

+0

建議一個解決方案,我會upvote – BlackBear 2011-05-20 15:49:21

+1

@BlackBear - 我的解決方案是使用6 printf的,而不是打擾這個黑客。 :-) – 2011-05-20 15:53:47

+0

這裏是:P(char limit) – BlackBear 2011-05-20 15:55:22

0

當你調用(int *)(InHeadP + i)時,你正在對尺寸爲24的mach_msg_header_t進行指針運算。所以你的第一次迭代是在結構的開始處,而你的第二次迭代就在你的結構之後。您正在訪問其他一些內存。

嘗試(((int *)InHeadP)+ i)。

0

等待第二個,這是錯誤的:

int deref = *((int*)(InHeadP+i)); 

你想

int deref == *((int*)InHeadP+i) 

您跳過每次24個字節通過循環,而不是4。

3

的優選方法迭代一個結構就是創建一個函數,該函數返回給定索引的字段的值或地址。需要注意的是,如果結構變化的成員的順序,這個功能也必須改變:

int * Index_Of(unsigned int index, mach_msg_header_t * p_struct) 
{ 
    switch (index) 
    { 
     case 0: return (int *) &(p_struct->msgh_bits); 
     case 1: return (int *) &(p_struct->msgh_size); 
     case 2: return (int *) &(p_struct->msgh_remote_port); 
     case 3: return (int *) &(p_struct->msgh_local_port); 
     case 4: return (int *) &(p_struct->msgh_reserved); 
     case 5: return (int *) &(p_struct->msgh_id); 
    } 
    return 0; 
} 

只要記住,治療的結構連續字段(成員),因爲編譯器被允許添加是不可取結構構件之間的填充。因此,除名稱之外的任何訪問字段的方法都是危險的,並且會導致非常困難的錯誤。

順便說一句,將每個字段視爲int也是危險的。如果任何類型更改爲其他內容,如double,則代碼將中斷。編譯器不會捕獲錯誤,因爲cast會告訴編譯器,您知道自己在做什麼。

你可以 「打開圖片周圍」 和實施遊客模式:

struct Visitor_Void 
{ 
    void (*fn_msgh_bits)(mach_msg_bits_t); 
    void (*fn_msgh_size)(mach_msg_size_t); 
    void (*fn_msgh_remote_port)(mach_port_t); 
    void (*fn_msgh_local_port)(mach_port_t); 
    void (*fn_msgh_reserved)(mach_msg_size_t); 
    void (*fn_msgh_id)(mach_msg_id_t); 
}; 


void Visit_Members(mach_msg_header_t * p_header, 
        struct Visitor_Void * p_visitor) 
{ 
    (p_visitor->fn_msgh_bits)(p_header->msgh_bits); 
    (p_visitor->fn_msgh_size)(p_header->msgh_size); 
    (p_visitor->fn_msgh_remote_port)(p_header->msgh_remote_port); 
    (p_visitor->fn_msgh_local_port)(p_header->msgh_local_port); 
    (p_visitor->fn_msgh_reserved)(p_header->msgh_reserved); 
    (p_visitor->fn_msgh_id)(p_header->msgh_id); 
    return; 
} 
+0

+1,用於警告不對佈局做出假設,特別是對於訪問者模式示例。 – Dan 2011-05-20 22:17:51

+0

我的問題是我不知道結構的佈局。消息標題繼續處理未知佈局。 – 2011-05-21 13:10:47