在C中:如何在运行时用offset指向不同的成员?
In C: How to point to different members with offset at run time?
我想使用单个指针 pt
和偏移量 size_t offp
来更新 myNFO.valueA
或 myNFO.valueB
的值取决于 运行 时间条件。
我可以将pt
设置为&myNFO
,但我不知道pt
的正确类型以及我应该如何计算offp
。
已编辑:
我忘了说我使用的结构是在运行时分配的。
我用的是khash,需要区分key是否存在。如果我使用pt = &pNFO->valueA;
,我必须写两次类似的代码。因此我想先确定哪个成员,然后再去hash。
typedef struct {
uint16_t valueA;
uint16_t valueB;
const char * fileName;
} __attribute__ ((__packed__)) Info_t;
Info_t myNFO, *pNFO;
pNFO = calloc(1,sizeof(Info_t));
size_t offp = &(myNFO.valueB) - &(myNFO.valueA);
if (ret==1) {
pt = pNFO;
} else {
pt = pNFO + offp;
}
*pt = 100;
你可以简单地做:
if (ret==1) {
pt = &pNFO->valueA;
} else {
pt = &pNFO->valueB;
}
如果打算让更多的成员考虑这样做:
typedef struct {
uint16_t value[MAX_VALUES];
const char * fileName;
} __attribute__ ((__packed__)) Info_t;
if (ret < MAX_VALUES) {
pt = &pNFO->values[ret];
}
因为pt
指向一个uint16_t
,它应该是一个uint16_t
指针:
uint16_t *pt;
我首先要说的是,您可能做错了。但是让你搬起石头砸自己的脚:
uint16_t* pt;
if (ret==1) {
pt = (uint16_t*)pNFO;
} else {
pt = (uint16_t*)pNFO + offp;
}
*pt = 100;
更好的方法是:
uint16_t* pt;
if (ret==1) {
pt = &pNFO->valueA;
} else {
pt = &pNFO->valueB;
}
*pt = 100;
使用offsetof()
size_t offp;
if (some condition) {
offp = offsetof(Info_t, valueA);
} else {
offp = offsetof(Info_t, valueB);
}
*(uint16_t*)((char*)pNFO + offp) = 100;
您需要进行所有指针转换,因为 offsetof()
returns 以字节为单位的偏移量。因此,首先您必须将结构指针转换为 char*
以向其添加字节,然后将其转换为指向要分配给它的元素类型的指针。
现在可以了。但我认为以这种方式设置 offset
看起来像 Magic Numbers,如果有更好的方法,我想避免这种情况。
typedef struct {
uint16_t insertSize;
uint16_t SD;
const char * fileName;
} __attribute__ ((__packed__)) BamInfo_t;
KHASH_INIT(bamNFO, kh_cstr_t, BamInfo_t, 1, kh_str_hash_func, kh_str_hash_equal)
bamNFOp = kh_init(bamNFO);
BamInfo_t tbam, *pbam;
while(READFILE) {
... ...
char * id = strdup(name);
uint16_t *pt;
size_t offset = 0;
if (strspn(".SD",name)==3) {
size_t idLen = strlen(name);
id[idLen-3] = '[=10=]';
offset = 1;
}
ki = kh_put(bamNFO, bamNFOp, id, &absent);
if (absent) {
kh_key(bamNFOp, ki) = id;
pt = (void*) &tbam;
*(pt+offset) = atol(value);
kh_value(bamNFOp, ki) = tbam;
} else {
free(id);
pt = (void*) &kh_value(bamNFOp, ki);
*(pt+offset) = atol(value);
}
}
我想使用单个指针 pt
和偏移量 size_t offp
来更新 myNFO.valueA
或 myNFO.valueB
的值取决于 运行 时间条件。
我可以将pt
设置为&myNFO
,但我不知道pt
的正确类型以及我应该如何计算offp
。
已编辑:
我忘了说我使用的结构是在运行时分配的。
我用的是khash,需要区分key是否存在。如果我使用
pt = &pNFO->valueA;
,我必须写两次类似的代码。因此我想先确定哪个成员,然后再去hash。
typedef struct {
uint16_t valueA;
uint16_t valueB;
const char * fileName;
} __attribute__ ((__packed__)) Info_t;
Info_t myNFO, *pNFO;
pNFO = calloc(1,sizeof(Info_t));
size_t offp = &(myNFO.valueB) - &(myNFO.valueA);
if (ret==1) {
pt = pNFO;
} else {
pt = pNFO + offp;
}
*pt = 100;
你可以简单地做:
if (ret==1) {
pt = &pNFO->valueA;
} else {
pt = &pNFO->valueB;
}
如果打算让更多的成员考虑这样做:
typedef struct {
uint16_t value[MAX_VALUES];
const char * fileName;
} __attribute__ ((__packed__)) Info_t;
if (ret < MAX_VALUES) {
pt = &pNFO->values[ret];
}
因为pt
指向一个uint16_t
,它应该是一个uint16_t
指针:
uint16_t *pt;
我首先要说的是,您可能做错了。但是让你搬起石头砸自己的脚:
uint16_t* pt;
if (ret==1) {
pt = (uint16_t*)pNFO;
} else {
pt = (uint16_t*)pNFO + offp;
}
*pt = 100;
更好的方法是:
uint16_t* pt;
if (ret==1) {
pt = &pNFO->valueA;
} else {
pt = &pNFO->valueB;
}
*pt = 100;
使用offsetof()
size_t offp;
if (some condition) {
offp = offsetof(Info_t, valueA);
} else {
offp = offsetof(Info_t, valueB);
}
*(uint16_t*)((char*)pNFO + offp) = 100;
您需要进行所有指针转换,因为 offsetof()
returns 以字节为单位的偏移量。因此,首先您必须将结构指针转换为 char*
以向其添加字节,然后将其转换为指向要分配给它的元素类型的指针。
现在可以了。但我认为以这种方式设置 offset
看起来像 Magic Numbers,如果有更好的方法,我想避免这种情况。
typedef struct {
uint16_t insertSize;
uint16_t SD;
const char * fileName;
} __attribute__ ((__packed__)) BamInfo_t;
KHASH_INIT(bamNFO, kh_cstr_t, BamInfo_t, 1, kh_str_hash_func, kh_str_hash_equal)
bamNFOp = kh_init(bamNFO);
BamInfo_t tbam, *pbam;
while(READFILE) {
... ...
char * id = strdup(name);
uint16_t *pt;
size_t offset = 0;
if (strspn(".SD",name)==3) {
size_t idLen = strlen(name);
id[idLen-3] = '[=10=]';
offset = 1;
}
ki = kh_put(bamNFO, bamNFOp, id, &absent);
if (absent) {
kh_key(bamNFOp, ki) = id;
pt = (void*) &tbam;
*(pt+offset) = atol(value);
kh_value(bamNFOp, ki) = tbam;
} else {
free(id);
pt = (void*) &kh_value(bamNFOp, ki);
*(pt+offset) = atol(value);
}
}