按地址访问元素

时间:2015-02-22 01:52:27

标签: c++ c memory struct

我做了一些研究,我无法在这里或谷歌找到我正在寻找的东西。有没有办法按地址访问客户中的元素(而不是使用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

3 个答案:

答案 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));