在C中:如何在运行时用offset指向不同的成员?

In C: How to point to different members with offset at run time?

我想使用单个指针 pt 和偏移量 size_t offp 来更新 myNFO.valueAmyNFO.valueB 的值取决于 运行 时间条件。

我可以将pt设置为&myNFO,但我不知道pt的正确类型以及我应该如何计算offp

已编辑:


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);
    }
}