我有一个指向结构的指针,我想通过反复试验获取所有成员。我试图通过将指针递增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 :(得分:5)
因为InHeadP
是mach_msg_header_t*
,所以向其添加一个整数实际上会将整数乘以sizeof(mach_msg_header_t)
,就好像你正在索引一个mach_msg_header_t
的数组(和实际上是数组索引的工作方式)。您需要在对其执行算术之前将InHeadP
投射到int*
,即便如此,因为结构有六个字段,i
应该只到达6,而不是24。
答案 1 :(得分: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;
}
请记住,将结构视为连续字段(成员)是不可取的,因为允许编译器在结构成员之间添加填充。因此,除了名称之外访问字段的任何方法都是危险的,并且将导致非常困难的错误。
BTW,将每个字段视为int
也很危险。如果将任何类型更改为其他类型,例如double
,则代码将中断。编译器不会捕获错误,因为转换告诉编译器你知道你在做什么。
您可以“转动图片”并实施访客模式:
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;
}
答案 2 :(得分:1)
不,你不应该这样做!
这里特别错误
for (int i = 0; i <= 24; i++)
{
int deref = *((int*)(InHeadP+i));
printf("InHeadP[%d]=%d\n",i,deref);
}
是你打印24个不同结构的第一个int。
答案 3 :(得分:0)
当你调用(int *)(InHeadP + i)时,你正在对mach_msg_header_t进行指针运算,大小为24.所以你的第一次迭代是在struct的开头,你的第二次迭代就在你的struct之后。您正在访问其他一些内存。
尝试(((int *)InHeadP)+ i)。
答案 4 :(得分:0)
等一下,这是错的:
int deref = *((int*)(InHeadP+i));
你想要
int deref == *((int*)InHeadP+i)
每次通过循环跳过24个字节,而不是4个。