[英]Access elements in Struct by Address
我已经进行了一些研究,但在这里或Google上找不到我想要的东西。 有没有一种方法可以通过地址(而不是通过使用customer [i] .bottles)访问Customer中的元素。 我无法修改结构,因此无法将属性放入数组中。
typedef struct Customer {
int id;
int bottles;
int diapers;
int rattles;
} Customer;
Customer customers[100];
void setValue(int custInd, int propertyInd) {
//propertyInd would be 1 for id, 2 for bottles
//Attempting to set customers[0].bottles
*(&customers[custInd]+propertyInd) = 5;
}
我以为我可以做到这一点,但是我遇到了很多错误。 我知道“瓶子”值将是客户地址在内存中的第二个空间,我不应该直接设置该位置。
我知道这可能是不正确的代码,但是我想了解如何以及为什么/不起作用。 我也保证我有理由尝试以传统方式做到这一点,哈哈
而不是使用propertyInd
,也许将偏移量传递到结构中。 这样,即使布局发生巨大变化(例如,如果开头包含非整数字段),代码也将起作用。
这是您可能的操作方式:
void setValue(int custInd, int fieldOffset) {
int *ptr = (int *)((char *)&customers[custInd] + fieldOffset);
*ptr = 5;
}
...
setValue(custInd, offsetof(Customer, bottles));
offsetof
是一个标准化的宏,它返回从结构开始到给定元素的偏移量(以字节为单位)。
如果你仍然想使用指数,就可以计算偏移量为propertyInd * sizeof(int)
,假设在struct各个领域是一个int
。
您不能这样做:
*(&customers[custInd]+propertyInd) = 5;
因为&customers[custInd]
的类型是struct Customer*
,而不是int *
。 因此, &customers[custInd]+propertyInd
与&customers + custInd + propertyInd
,换句话说, &customers[custInd + propertyInd]
。 然后,赋值尝试将结构值设置为整数5
,这显然是非法的。
我想你的意思是
((int*)&customers[custInd])[propertyInd] = 5;
可以很好地编译,并且可能可以工作[*],但是它是未定义的行为,因为您不能仅假设结构由四个int
组成,就将其布局在内存中的方式与int[4]
相同。 它们的布局相同似乎是合理的,甚至是合乎逻辑的,但是标准并不需要它,仅此而已。 抱歉。
就像@iharob在评论中建议的那样,您可能会发现一个足够聪明的编译器可以从以下语言中生成有效的代码:
void setValue(int custInd, int propertyInd, int value) {
//propertyInd would be 1 for id, 2 for bottles
switch (propertyInd) {
case 1: customers[custInd].id = value; break;
case 2: customers[custInd].bottles = value; break;
case 3: customers[custInd].diapers = value; break;
case 4: customers[custInd].rattles = value; break;
default: assert(0);
}
}
*:实际上,如果id
propertyInd
为0,而不是1,则(可能)有效。C数组索引从0开始。
&customers[custInd]
是指向customers[custInd]
所以&customers[custInd]+propertyInd
是一个指针,指向customers[custInd+propertyInd]
它不是指向成员的指针。 它将具有指向Customer
类型指针。 该指针的值将等于&(customers[custInd+propertyInd].id)
,但它不是指向int的指针-因此会出现编译器错误。
您更大的问题是,结构中的四个int
不一定像int
数组那样进行布局-结构成员之间可能存在填充。 所以,如果我们这样做
int *p = &(customers[custInd].id);
那么p + 1不一定等于&(customers[custInd].bottles)
。
所以你需要做类似的事情
void setValue(int custInd, int Offset)
{
int *ptr = (int *)(((char *)&customers[custInd]) + Offset);
*ptr = 5;
}
/* and to call it to set customers[custInd].bottles to 5 */
setValue(custInd, offsetof(Customer, bottles));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.