[英]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.