2011-05-20 55 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