按地址访问结构中的元素
Access elements in Struct by Address
我做了一些研究,在这里或谷歌上找不到我想要的东西。有没有一种方法可以通过地址访问Customer中的元素(而不是使用Customer[i].parts)。我无法修改结构,因此无法将属性放入数组中。
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
,不如将偏移量传递到结构中。这样,即使布局发生了巨大变化(例如,如果开头包含非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
。
你不能这样做:
*(&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不一定等于CCD_ 24。
所以你需要做一些类似的事情
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));
- 使用不带参数的函数访问结构元素
- 带结构的二维矢量:如何存储元素
- 访问类lintalizer列表中的结构元素
- 如何为 c++ 的不同变量类型的结构元素创建动态数组?
- 设计将引用元素移动到开头的数据结构.C++
- 结构元素名称要 cout?
- C++:添加新结构时,结构指针向量中的所有元素都会更新
- 从指向结构数组的指针中提取元素
- 继承层次结构并将元素添加到向量
- 在集合中查找使用结构C++的元素
- C++结构元素(成员变量)的数量
- 无法在 Mosquitto MQTT Broker 插件上访问结构体 mosquitto 的元素
- 在C++中更改结构内部元素的方法?
- 保持排序的数据结构,允许log N插入时间,并且可以返回我在log N中查找的元素的索引
- 如何为结构的数据元素赋值
- 如何使用矢量元素将项目添加到结构中?
- 获取结构 c++ 中元素的索引
- C++ STL 数据结构常时按索引推送/弹出/随机访问,并具有指向元素的可靠指针
- 指向结构的指针向量的元素具有相同的地址
- 为什么将函数的返回类型从结构节点*更改为void后,链表的元素没有显示create_ll和显示?