2009-07-29 3 views
3

In meinem eingebetteten c-Programm habe ich eine Struktur:C Pointer Frage

struct var{ 
    unsigned long value; 
    unsigned long length; 

    + More 
} 

Ein Array dieser Strukturen wird verwendet, um Variablen zu halten. Die meisten der gespeicherten Variablen werden einfach in 'value' gespeichert und die Länge wird auf 1 gesetzt.
Einige dieser Variablen sind jedoch Arrays und ich versuche, die Startadresse in 'value' zu speichern.

unsigned long lookup[10]; 
variables[x].length = 10; 

Dann bin ich nicht ganz sicher, wie die Adresse zu speichern ...

variables[x].value = lookup; 
// lookup is a pointer so I cant put it into value 

ODER

variables[x].value = (unsigned long)lookup; 
// value reads back through sprintf+uart as '536874692' 
// which couldnt be a valid memory address! 

ich könnte nur eine Zeigervariable in der Struktur geben und füge

EDITIEREN:
Ich wollte vermeiden, den Zeiger zur Struktur hinzuzufügen, da ich zurückgehen und die Flash-Lese-/Schreibfunktionen neu schreiben müsste, um den Zeiger zu speichern. Diese sind ziemlich kompliziert und funktionieren derzeit, also würde ich sie lieber nicht anfassen!

+0

Warum konnte 536874692 keine gültige Adresse sein? – jalf

+0

Das ist mir gerade klar geworden. 536874692 ist 20000EC4, die wahrscheinlich gültig ist ... – Tim

+0

Beachten Sie, dass, wenn Ihre "Flash-Lese-/Schreibfunktionen" nicht wissen, dass Nachschlagen ein Zeiger ist, sie nicht wissen, um die Daten zu speichern, auf die es zeigt. – caf

Antwort

5

Sie könnte die Adresse in value speichern, indem Sie es auf eine unsigned long werfen, wie Sie demonstrieren. (Ich denke, der Wert, den Sie bekommen ist eine gültige Adresse ... in hex, kommt es wie 0x20000EC4 aus ... sieht aus wie Embedded Systems Datensegment bei 0x20000000 startet, nicht wahr?)

jedoch Gießen Zeiger auf Ints (oder Longs) sind niemals "sauber". Warum nicht ein

unsigned long *starting_address; 

zu Ihrer Struktur hinzufügen? Dann können Sie die Typumwandlungen vermeiden. Wenn Sie befürchten, dass dafür mehr Speicher benötigt wird, können Sie eine Union verwenden, die entweder unsigned long *starting_address oder einen "unsigned long value" speichert, der immer noch sauberer ist als das Casting.

+0

sieht aus wie 0x20000EC4 ist gültig, Danke. – Tim

0

Ich sehe nicht den Nachteil, einen Zeiger in Ihrer Struktur zu setzen. Soll der Speicher in einem kontinuierlichen Block sein? Sie könnten einfach tun

struct var 
{ 
    unsigned long *value; 
    unsigned long length; 

    unsigned long othervalue1; 
    unsigned long othervalue2; 
}; 

Aber nicht vergessen, Speicher für Wert getrennt zuweisen, indem Sie malloc verwenden. Oder wenn es eine feste Menge an Speicherplatz ist, den Sie verwenden möchten

+0

Ich wollte vermeiden, den Zeiger der Struktur hinzuzufügen, weil ich zurückgehen und meine Flash-Lese-/Schreibfunktionen neu schreiben müsste, um den Zeiger auch zu speichern. Nur der Wert wird im Flash gespeichert und alle anderen Strukturelemente (nicht gezeigt) werden manuell ausgefüllt. – Tim

0

Was passiert, wenn Sie Sprint + Uart Lookup. Welchen Wert gibt dir das?

Sofern keine Casting- oder Zeichenerweiterung vorhanden war, sind die tatsächlichen Daten identisch. Es wird nur anders interpretiert von sprintf.

Ihre Lösung, einfach einen Zeiger zu verwenden, ist gut. Wenn Sie wirklich einen int verwenden möchten, sollten Sie intptr_t verwenden, das garantiert groß genug ist, um einen Zeiger zu enthalten.

6

Eine sauberere Option wäre die Verwendung Union.

struct var{ 
    union { 
     unsigned long numeric; 
     void *ptr; 
    } value; 
    unsigned long length; 

    + More 
} 

Sie können optional auch einen Typ enum hinzufügen, wie es oft bei Union-using-Stücken der Fall ist.

1

Angenommen, die Systemzeigergröße ist die gleiche wie die eines unsigned long (keine Garantie, überprüfen Sie es mit sizeof) Sie würden die Besetzung verwenden. Aber das ist chaotisch und fehleranfällig. Erwägen Sie stattdessen, eine Union zu verwenden.

struct var{ 
    unsigned short type; 
    union { 
     unsigned long i; 
     void *p; 
    } value; 
    unsigned long length; 

    + More 
} 

wo Sie den Typ in type speichern.

0

Warum den Wert nicht zu einem einlangen Array machen, wenn die Länge 1 ist? Sie werden sowieso nicht mehr Platz brauchen.

0

Ich bin mir nicht sicher, warum Sie Wert nicht als unsigned long * definieren.

Stattdessen tun so etwas wie:

struct var{ 
    union{ 
    unsigned long solo_value; 
    unsigned long* multi_values; 
    } 

    unsigned long length; 
    + More 
}; 

Auch sind Ausrichtungsregeln nicht so stark * auf den Stapel durchgesetzt, wie sie in dem Haufen sind. Allerdings, wenn Sie einen neuen Compiler verwenden, sollten sie trotzdem ... Sie sind wahrscheinlich etwas mit Sprintf zerschlagen. Ziehen Sie den Wert mit einem Debugger oder etwas zuverlässiger.

* Technisch malloc() et. al. Erzwingen Sie die 8-Byte-Ausrichtungsregeln, nicht die Sprache.

0

Ihre beste Wahl ist eine Enum, zu verwenden, wie bereits erwähnt:

typedef struct var{ 
    union { 
     unsigned long numeric; 
     void *ptr; 
    } value; 
    unsigned long length; 

    // + More 
} composition_t; 

dann die Länge Mitglied verwenden, um die Art von Daten zu unterscheiden:

composition_t array[2]; 
unsigned long lookup[10]; 

// Just a plain unsigned long value 
array[0].value.numeric = 100; 
array[0].length= 1; 

// An array of 10 long values 
array[0].value.ptr= lookup; 
array[x].length = 10; 
0

Bär in Beachten Sie, dass ein unsigned long nicht unbedingt einen Zeiger enthält, obwohl dies in eingebetteten Systemen wahrscheinlich ist. Tun Sie das Standard-Ding und verwenden Sie eine Vereinigung, wie andere Antworten vorschlagen. Eine Union wird in jeder standardkonformen Implementierung das Richtige tun, nicht nur, was Sie gerade verwenden. Außerdem hat es den Vorteil zu sagen, was du meinst, was immer wertvoll ist, wenn jemand, der nicht sofort den Code knackt (vielleicht musst du, ein Jahr später) damit fertig werden.

0

Ist Ihnen offsetof bekannt? http://en.wikipedia.org/wiki/Offsetof

Ich bin mir nicht sicher, was Sie wirklich versuchen, aber die Adresse eines Strukturelements in der gleichen Struktur speichern scheint unnötig.

Es gibt auch ein container_of-Makro (google it), das mit offsetof erstellt wird und das könnte auch nützlich sein.