Forum: Compiler & IDEs Pointer auf Integerwert im Flash (ohne explizit eine Variable anzulegen)


von Thomas F. (thomas-hn) Benutzerseite


Lesenswert?

Hallo,

ist es mit C möglich einen Integerwert im Flash abzulegen, ohne dafür 
einen Variablennamen zu definieren und nur die Adresse dieses Wertes im 
Speicher zu bekommen? Also sowas wie:
1
int* MyPtr = &(const int)1234;

Bei Strings verhält es sich ja im Prinzip ähnlich. Dort liegt der String 
auch irgendwo im Flash und ich bekomme einen Zeiger darauf:
1
char* MyPtr = "HelloWorld";

Eine Alternative wäre ja z.B. meine Zahl 1234 (Hex: 0x04D2) als String 
abzulegen, allerdings mit dem Nachteil, dass ich beim Zugriff die Daten 
unter Umständen wieder in der korrekten Reihenfolge zusammenbauen 
müsste:
1
char* MyPtr = "\x04\xD2";

Vielen Dank,

Thomas

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Thomas F. schrieb:
> Hallo,
>
> ist es mit C möglich einen Integerwert im Flash abzulegen, ohne dafür
> einen Variablennamen zu definieren und nur die Adresse dieses Wertes im
> Speicher zu bekommen? Also sowas wie:
>
>
1
> int* MyPtr = &(const int)1234;
2
>
1
int* MyPtr = (int*)1234;

von GCC (Gast)


Lesenswert?

Das geht etwa so:
1
*((uint32_t*)1234) = 0xDEADBEEF;

Vorrausgesetzt, mein C-Fu ist noch nicht so eingerostet bzw. es ist 
Semantisch erlaubt

von Thomas F. (thomas-hn) Benutzerseite


Lesenswert?

Torsten R. schrieb:
> Thomas F. schrieb:
>> Hallo,
>>
>> ist es mit C möglich einen Integerwert im Flash abzulegen, ohne dafür
>> einen Variablennamen zu definieren und nur die Adresse dieses Wertes im
>> Speicher zu bekommen? Also sowas wie:
>>
>>
1
>> int* MyPtr = &(const int)1234;
2
>>
>
>
1
> int* MyPtr = (int*)1234;
2
>
Hier typecaste ich die 1234 ja nur in einen Pointer und verwende die 
1234 somit als Adresse für meinen MyPtr.


GCC schrieb:
> Das geht etwa so:
>
>
1
*((uint32_t*)1234) = 0xDEADBEEF;
>
> Vorrausgesetzt, mein C-Fu ist noch nicht so eingerostet bzw. es ist
> Semantisch erlaubt
Hier typecaste ich die 1234 ja auch in einen Pointer, dereferenziere 
diesen dann und weise der Speicherstelle 0xDEADBEEF zu.

Was ich aber möchte ist, dass der Wert (nicht Adresse) 1234 im Flash 
abgelegt wird und ich die Adresse auf diesen Speicherplatz bekomme, 
sodass ich mit folgender Zeile auf mein 1234 zugreifen könnte:
1
MeinVariablenwert = *MyPtr;

von Stefan F. (Gast)


Lesenswert?

Um welchen Mikrocontroller geht es?
Warum willst du keine Variable deklarieren?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Thomas F. schrieb:
> Hallo,
>
> ist es mit C möglich einen Integerwert im Flash abzulegen,

Der C-Standard kennt kein Konzept namens "Flash".

Unabhängig davon gibt es keine Möglichkeit, die Adresse auf eine Zahl zu 
bekommen wenn z.B. eine Funktion einen int* erwartet:
1
extern void with_int (int*);
2
3
void provide_int (void)
4
{
5
    int val = 1234;
6
    with_int (&val);
7
}

In GNU-C geht auch z.B. fogendes:
1
extern void with_cint (const int*);
2
3
#define ADDRESS_OF(VAL) ({ static const int _[] = { (VAL) }; _;})
4
5
void provide_cint (void)
6
{
7
    with_cint (ADDRESS_OF (1234));
8
}

Ob der Wert ins Flash gelegt wird hängt jedoch vom ABI der 
C-Implementierung ab.

von Frank (Gast)


Lesenswert?

Warum sagt man nicht einfach dem Linker, dass er   die Variable const 
int val; im Flash platzieren soll und legt dann einen Pointer darauf an?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Anonyme Variablen kann man mit Compound-Literals erzeugen:

1
const int *MyPtr = &(const int){ 1234 };

Manche Compiler platzieren const-Objekte automatisch im Flash, bei
anderen muss man etwas nachhelfen. So muss man bspw. beim AVR-GCC das
Schlüsselwort __flash verwenden:

1
const __flash int *MyPtr = &(const __flash int){ 1234 };

: Bearbeitet durch Moderator
von Kaj (Gast)


Lesenswert?

Und wozu genau ist das ganze gut? :-/

von Thomas F. (thomas-hn) Benutzerseite


Lesenswert?

Yalu X. schrieb:
> Anonyme Variablen kann man mit Compound-Literals erzeugen:
>
>
>
1
> const int *MyPtr = &(const int){ 1234 };
2
>

Genial, sowas habe ich gesucht :-)
Eine Frage allerdings noch.
Wenn ich deine oben zitierte Variante nehme, meldet mir der Compiler:
"taking address of temporary".

Bei der folgenden Variante compiliert es ohne Errors und Warnings.
1
const int *MyPtr = (const int[]){ 1234 };

Wieso behandelt der Compiler hier die "Adresse von einem Integer" nicht 
gleich wie ein Array (ein Verweis auf das Array selbst ist doch auch nur 
ein Zeiger).

von Yalu X. (yalu) (Moderator)


Lesenswert?

Thomas F. schrieb:
> Wieso behandelt der Compiler hier die "Adresse von einem Integer" nicht
> gleich wie ein Array (ein Verweis auf das Array selbst ist doch auch nur
> ein Zeiger).

Keine Ahnung. Was ist das für ein Compiler?

Man muss halt beachten, dass ein Compound-Literal, das innerhalb einer
Funktion steht, nur so lange lebt, wie der umschließende Block aktiv
ist. Ist die Zeigervariable, die auf das Literal zeigt, länger existent,
wird ihr Inhalt ungültig. Das ist dann so ein ähnlicher Effekt wie wenn
eine Funktion einen Zeiger auf eine nicht-statische lokale Variable als
Return-Wert zurückgibt. Beide Problem bestehen aber bei einem durch
einen Zeiger repräsentierten Array genauso, weshalb auch mir ganz klar
ist, warum der Compiler in einem Fall warnt und im anderen nicht.

Compound-Literals außehalb von Funktionen sind übrigens immer statisch,
leben also so lange, wie das Programm läuft.

von Thomas F. (thomas-hn) Benutzerseite


Lesenswert?

Als Compiler verwende ich hier gerade die Codeblocks IDE mit GNU GCC.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Kannst du ein kleines Beispiel posten, bei dem die Warnung ausgegeben
wird?

von Stefan F. (Gast)


Lesenswert?

Und benenne auch den µC (MCU), für den du das compilierst.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Thomas F. schrieb:
> Wieso behandelt der Compiler hier die "Adresse von einem Integer" nicht
> gleich wie ein Array (ein Verweis auf das Array selbst ist doch auch nur
> ein Zeiger).

Weil ein Array kein Zeiger ist und ein Zeiger kein Array.

1) sizeof verhält sich anders.

2) Einem Zeiger kann ein Wert zugewiesen werden, einem Array nicht
   (damit ist nicht ein Element des Arrays gemeint).
1
void test (void)
2
{
3
   int *p;
4
   int array[5];
5
6
   p = array; // Ok
7
   array = p; // Fehler
8
9
   sizeof (p);     // = sizeof (int*)
10
   sizeof (array); // = 5 * sizeof (int)
11
}

von Stefan F. (Gast)


Lesenswert?

Ich wiederhole nochmal die Fragen der Fragen:

> Um welchen Mikrocontroller geht es?
> Warum willst du keine Variable deklarieren?

> Und wozu genau ist das ganze gut?

Wer Hilfe erwartet, sollte Rückfragen beantworten.

von Yalu X. (yalu) (Moderator)


Lesenswert?

@Thomas:

Mir scheint, du kompilierst den Code als C++-Programmm.

In C++ gibt es offiziell keine Compound-Literals, allerdings bietet sie
der GCC als Erweiterung an. Dummerweise verhalten sich die Compound-
Literals im erweiterten C++ anders als in C:

  https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html

Wenn du den verlinkten Text gelesen hast, verstehst du die Fehlermeldung
und auch, warum bei Verwendung eines Arrays mit const-Elementen keine
Fehlermeldung ausgegeben wird.

In C sind beide Schreibweisen gleichbedeutend und korrekt, weswegen der
Compiler dort nicht meckert.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.