我做了一些研究,我无法在这里或谷歌找到我正在寻找的东西。有没有办法按地址访问客户中的元素(而不是使用customer [i] .bottles)。我无法修改结构,因此我无法将属性放入数组中。
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;
}
我以为我能做到这一点,但我遇到了各种各样的错误。知道“瓶子”值将是客户地址中的第二个内存空间,我不应该直接设置这个位置。
我知道这可能是不正确的代码,但我想了解如何以及为什么/不起作用。我也保证我有理由尝试以传统的方式做到这一点hah
答案 0 :(得分:2)
可能会将偏移传递给结构,而不是使用propertyInd
。这样,即使布局发生显着变化,代码也会起作用(例如,如果它在开头包含非int字段)。
以下是如何做到的:
void setValue(int custInd, int fieldOffset) {
int *ptr = (int *)((char *)&customers[custInd] + fieldOffset);
*ptr = 5;
}
...
setValue(custInd, offsetof(Customer, bottles));
offsetof
是一个标准化的宏,它返回从结构的开头到给定元素的偏移量(以字节为单位)。
如果您仍想使用索引,则可以将偏移计算为propertyInd * sizeof(int)
,假设结构中的每个字段都是int
。
答案 1 :(得分:0)
你不能这样做:
*(&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);
}
}
*:实际上,如果propertyInd
的{{1}}为0而不是1,它(可能)会起作用.C数组索引从0开始。
答案 2 :(得分: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));