PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Adresse eines struct-Elements ermitteln???



cl
21.04.2007, 11:37
Hallo,

ich habe eine größere struct (ca. 200Bytes), die in einem extern angeschlossenen RAM gespeichert wird (viele Kopien davon). Das RAM wird nicht über die Hardwaremäßig beim ATMega128 vorgesehenen Pins angesprochen, sondern über eigene Routinen, ich habe sie dram_read_rc und dram_write_rc genannt. Es handelt sich um ein DRAM, das ich von einem alten 30poligen Modul 'gerippt' habe.

Da die Struktur recht groß ist, und einige der Werte deutlich öfter gelesen werden müssen als andere, lohnt es nicht die ganze Struktur zu laden (RAM + Laufzeit des Codes).
Wenn ich nun aus der Struktur aber nur ein Element lesen will (z.B. einen uint16_t), dann muß man ja wissen, wo vom Beginn der Struktur im Speicher an gerechnet dieses Element gespeichert ist. Diesen Wert hartzucoden finde ich, scheidet aus, weil mit Optimierung etc. oder Veränderungen an der Struktur artet das schnell in Arbeit aus. Ist auch ne tolle Fehlerquelle bei ca. 70kByte Source-Code.

Wenn man die Struktur im RAM anlegen kann ist es ja natürlich keine Herausforderung (die struct ts ist _natürlich_ nicht die richtige Struktur). Ich habe versucht, dass mal mit diesem Programm deutlich zu machen.

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

struct ts {
uint16_t a;
uint16_t b;
uint8_t c;
uint16_t d;
};

int main (void)
{
struct ts x;
int the_offset;

// calculate the offset (cast required as data types are different!)
the_offset = ((char *) &x.d) - ((char *) &x);

printf("offset %d required to access structure element 'd' directly\n", the_offset);
}


Aber wie mache ich dasselbe, ohne die Struktur anzulegen??? Ich möchte ja eben nur die Adresse vom Element d innerhalb der Struktur.

Nutze avr-gcc 4.1.2.

TIA für alle Hinweise
- cl

cl
21.04.2007, 11:40
für alle die es interessiert, hier noch ein Bild der Platine :)
Die Platine habe ich mit dem Conrad-Laminator laminiert, aber das ist ja eigentlich OT.

SprinterSB
21.04.2007, 12:40
Du kannst ja über die Adressen gehen.



void foo (void)
{
foo_t * bar;
int offset = (int) & bar->x - (int) bar;
...
}

Aber sowas brauchst du nicht. Du kannst ja die ganze Struktur kopieren, also ab ihrem Anfang (als unsigned char*) einfach die Anzahl der Bytes (sizeof...). Falls du nicht die gesamze STruktur willst, dann organisierst du sie eben in Teil/Unterstrukturen.

cl
21.04.2007, 16:24
Tja, man sieht man kommt doch nicht auf alles. Danke für den Tipp. Jetzt sieht meine "App" so aus:



#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

struct ts {
uint16_t a;
uint16_t b;
uint8_t c;
uint16_t d;
};

int main (void)
{
struct ts *p;
int the_offset;

// calculate the offset (cast required as data types are different!)
the_offset = ((char *) &p->d) - ((char *) p);

printf("offset %d required to access structure element 'd' directly\n", the_offset);
}


BTW: Du castest wie ganz selbstverständlich die Pointer auf int. Ich kenne den C-Standard nicht genau genug, aber ist garantiert, dass int die selbe Größe wie int hat??? Auf AVR, 8051 und x86 ja, aber sonst?

CowZ
21.04.2007, 18:01
Nein, eigentlich nicht.

Es gibt ja 8-Bit-Systeme (die von die angesprochenen) und 32- oder mittlerweile auch 64-Bit-Systeme, auf denen ein Int entsprechend länger ist. Daher sollte man auch lieber uint8_t benutzen.

Gruß, CowZ