2016-06-10 18 views
-3

Ich möchte einen einzelnen Zeiger pt und einen Offset size_t offp verwenden, um den Wert von myNFO.valueA oder myNFO.valueB abhängig von Laufzeitbedingungen zu aktualisieren.In C: Wie zeigt man zur Laufzeit auf verschiedene Elemente mit Offset?

kann ich pt-&myNFO gesetzt, aber ich weiß nicht, die richtige Art von pt und wie soll ich offp berechnen.

Edited:

  • ich vergessen, die Strukturen zu erwähnen, ich verwendet werden zur Laufzeit zugeordnet.

  • Ich verwende khash, die unterscheiden müssen, ob ein Schlüssel existiert. Wenn ich pt = &pNFO->valueA; verwende, muss ich ähnliche Codes zweimal schreiben. Also möchte ich zuerst bestimmen, welches Mitglied und dann zum Hash-Code wechseln.


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; 
+1

Der Compiler erledigt das für Sie, wenn Sie 'myNFO.valueB' schreiben. Wenn Sie über einen Zeiger auf ein Element zugreifen wollen, können Sie 'pNFO-> valueB' verwenden. Der Compiler führt die gleiche Offset-Berechnung durch. – Tim

+0

Warum nicht nur 'uint16_t * pt = ret == 1? & pNFO-> valueA: & pNFO-> valueB; '? – melpomene

+0

Warum verwenden Sie nicht 'offsetof()'? – Barmar

Antwort

1

Verwenden offsetof()

size_t offp; 
if (some condition) { 
    offp = offsetof(Info_t, valueA); 
} else { 
    offp = offsetof(Info_t, valueB); 
} 
*(uint16_t*)((char*)pNFO + offp) = 100; 

Sie müssen alle Zeiger Casting tun, weil offsetof() zurückkehrt der Offset in Bytes. Zuerst müssen Sie den struct-Zeiger auf char* umwandeln, um ihm die Bytes hinzuzufügen, und ihn dann in einen Zeiger auf den Elementtyp umwandeln, der ihm zugewiesen werden soll.

+0

Ich bemerke gerade 'size_t offsetof (type, member);' benutzt 'type'. – Galaxy

+0

Und ich denke '* (uint16_t *) ((void *) pNFO + offp) = 100;' sollte besser sein, da 'void' typenfrei ist. – Galaxy

+0

Sie können nicht zu einem 'void *' hinzufügen. – Barmar

0

Sie können einfach tun:

if (ret==1) { 
    pt = &pNFO->valueA; 
} else { 
    pt = &pNFO->valueB; 
} 

Wünscht viele mehr Mitglieder haben, ist in Erwägung ziehen:

typedef struct { 
    uint16_t value[MAX_VALUES]; 
    const char * fileName; 
} __attribute__ ((__packed__)) Info_t; 


if (ret < MAX_VALUES) { 
    pt = &pNFO->values[ret]; 
} 

seit pt zeigt auf ein uint16_t sollte es sein ein uint16_t Zeiger:

uint16_t *pt; 
+0

Ich verwende 'Info_t' als Wert einer Hash-Tabelle. Wenn ich zuerst 'pNFO' setze, muss ich 2 ähnliche Codes schreiben, ob der Schlüssel existiert. – Galaxy

0

Ich werde zunächst sagen, dass Sie wahrscheinlich dies den falschen Weg tun. Aber Sie selbst in den Fuß schießen zu lassen:

uint16_t* pt; 
if (ret==1) { 
    pt = (uint16_t*)pNFO; 
} else { 
    pt = (uint16_t*)pNFO + offp; 
} 
*pt = 100; 

Eine bessere Möglichkeit wäre:

uint16_t* pt; 
if (ret==1) { 
    pt = &pNFO->valueA; 
} else { 
    pt = &pNFO->valueB; 
} 
*pt = 100; 
+0

Ich verwende [khash] (https://github.com/attrtractivechaos/klib/blob/master/khash.h) der Struktur, somit wird sie zur Laufzeit zugeordnet. – Galaxy

+2

@Galaxy Warum ist es wichtig, dass es zur Laufzeit zugeordnet ist? – melpomene

+0

Strukturen sind ein Kompilierzeitobjekt. Meinst du, dass der Speicher für die Struktur zur Laufzeit zugeordnet ist? Macht keinen Unterschied. –

0

Es funktioniert jetzt. Aber ich denke, Einstellung offset auf diese Weise scheint wie Magic Numbers, und ich möchte dies vermeiden, wenn es einige bessere Möglichkeit gibt.

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] = '\0'; 
     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); 
    } 
}