mikrocontroller.net

Forum: Compiler & IDEs NULL in bare metal system


Autor: Daniel G. (motello)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte NULL in meinem bare metal programm (ohne BS) nutzen. Ich 
benutze newlib. Wenn ich string.h einbinde, ist auch ein NULL pointer 
definiert. Kann ich den bedenkenlos nutzen? wohin zeigt er?

toolchain: codesouercery

Grüße
Daniel

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel G. schrieb:
> Hallo,
>
> ich möchte NULL in meinem bare metal programm (ohne BS) nutzen. Ich
> benutze newlib. Wenn ich string.h einbinde, ist auch ein NULL pointer
> definiert. Kann ich den bedenkenlos nutzen?

Mit einem NULL kann man eigentlich nur eines tun: Anzeigen, dass der 
Pointer nirgendwo Sinnvolles hinzeigt.

> wohin zeigt er?

Nirgendwo hin.

Autor: Daniel G. (motello)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Nirgendwo" liegt aber nicht im Bereich von 32bit Variablen. Kann ich 
ihn bedenkenlos nutzen? (Um eben keinen gültigen Pointer sondern "kein 
pointer" zurückzugeben)?

Ist NULL vielleicht immer als (void*) 0 deklariert?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Pointer zeigt auf ein C Handbuch. Dass du evtl. mal lesen 
solltest.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel G. schrieb:

> Ist NULL vielleicht immer als (void*) 0 deklariert?

Definiert!

Ja, das ist es.

Selbst dann, wenn an der Speicherzelle 0 bedenkenlos geschrieben/gelesen 
werden kann :-)

Autor: BimmyundJimmy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ist NULL vielleicht immer als (void*) 0 deklariert?

Nein! Laut C-Standard ist das nicht zwingend!
Ich meine, dies ist auch in dem Buch "Von C zu C" erwähnt!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
BimmyundJimmy schrieb:
>> Ist NULL vielleicht immer als (void*) 0 deklariert?
>
> Nein! Laut C-Standard ist das nicht zwingend!

Du hast recht, der void cast wird nicht gefordert. In C++ ist er sogar 
explizit verboten.

Aber der 'ungültige Pointer' hat immer für den C-Programmierer den 
Zahlenwert 0. Ob er das intern auch hat, ist Sache des Compilers. Für 
dich als C-Programmierer ist jeder Ausdruck der 0 ergibt ein vollkommen 
gültiger 'Pointer ins Nirgendwo'

> Ich meine, dies ist auch in dem Buch "Von C zu C" erwähnt!

Schön.
Schreib einen Bugbericht an den Autor und verweise ihn auf den 
Sprachstandard.

Autor: Horst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Kann ich ihn bedenkenlos nutzen? (Um eben keinen gültigen Pointer sondern
>> "kein pointer" zurückzugeben)?

Nein. Aber du kannst ihn nutzen, um einen als ungültig erkennbaren 
Pointer zurückzugeben.
Es ist aber immer noch ein Pointer, der auch verwendet werden kann wie 
jeder andere Pointer auch. Nur sinnvoll ist es halt nicht.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Nur sinnvoll ist es halt nicht.

Es sei denn, es liegt RAM an der Adresse 0 und man möchte darauf 
zugreifen.

So etwas macht man aber i.d.R. nicht aus C-Programmen heraus.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gab mal eine ganz üble Plattform für sowas. Eine Architektur mit 
vorzeichenbehaftetem Adressraum, also bei den 16bit-Versionen von 
-0x8000 bis +0x7FFF (INMOS Transputer T212). Da war kaum zu verhindern, 
dass 0 genau mittem im Speicher liegt. Bei den 32bit-Versionen war das 
zwar auch so, aber damals kein Problem.

Autor: Andreas Schweigstill (Firma: Schweigstill IT) (schweigstill) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Rufus t. Firefly schrieb:
> Es sei denn, es liegt RAM an der Adresse 0 und man möchte darauf
> zugreifen.

Es gibt dann aber auch noch solche Dep..., ähh merkbefreiten
Entwickler, die bei einer NULL-Pointer-Zuweisung schreiben:

int * a;

a = *NULL;

statt

a = NULL;

Da es leider etliche solcher Fälle gibt, wurde bei Solaris eine
Bibliothek namens lib0@0.so (oder so ähnlich) eingeführt, die nichts
anderes enthält als den Speicherinhalt 0x00000000 bzw 0x0000000000000000
an Adresse 0. Somit erhält a dann keinen anderen Wert als 0.

Vor etlichen Jahren fand ich bei einem ARM7-basierten Projekt einen
kleinen Fehler. Bei der Systeminitialisierung wurde die im ROM befind-
liche Vektortabelle ins RAM kopiert und anschließend eine Bank-
vertauschung durchgeführt. Kurz danach wurde auf Grund eines nicht
initialisierten Pointers der Wert 0 an Adresse 0  geschrieben. Diesen
Fehler korrigierte ich und trat dabei eine Lawine los.

Plötzlich funktionierten etliche andere Teile der Software nicht mehr.

Wie sich nämlich herausgestellt hatte, gab es in dem Projekt mindestens
zwei andere Entwickler, die die o.a. Zuweisungen (a = *NULL) und
entsprechende Abfragen (if (a == *NULL)) in das ganze Projekt gestreut
hatten...

MfG
Andreas Schweigstill

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Nur sinnvoll ist es halt nicht.
>
> Es sei denn, es liegt RAM an der Adresse 0 und man möchte darauf
> zugreifen.

In C ist es aber nicht garantiert, daß ein Nullzeiger auch wirklich eine 
Adresse enthält, deren Bits alle 0 sind.

Autor: Andreas Schweigstill (Firma: Schweigstill IT) (schweigstill) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Rolf Magnus schrieb:
> In C ist es aber nicht garantiert, daß ein Nullzeiger auch wirklich eine
> Adresse enthält, deren Bits alle 0 sind.

Es ist nicht durch den Sprachstandard garantiert, aber ggf. aus der
Kombination aus Sprachstandard, Prozessorarchitektur und Compiler.
Sofern man also keine beliebig portablen Programme schreiben muss, kann
man sich im Einzelfall aber doch darauf verlassen und muss wohl auch
nicht befürchten, dass sie der Compiler in Abhängigkeit von der
Mondphase neu entscheiden wird, wie er einen Nullzeiger darstellt.

Wenn man bei einer portablen Anwendung jedoch Annahmen bezüglich der
Implementierung macht, kann man die betreffenden Stellen ja auch per
Präprozessormakro absichern und einen Abbruch der Kompilierung bei einem
unbekannten Compiler oder Prozessor veranlassen.

MfG
Andreas Schweigstill

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn man bei einer portablen Anwendung jedoch Annahmen
> bezüglich der Implementierung macht, kann man die betreffenden
> Stellen ja auch per Präprozessormakro absichern und einen Abbruch
> der Kompilierung bei einem unbekannten Compiler oder Prozessor
> veranlassen.

Oder man macht daraus:
int i = 0;
void* p = (void*)i;

Das ist zwar auch keine Garantie, aber man umgeht damit zumindest die 
Sonderbehandlung von 0 im Zeigerkontext. Dann braucht man wenigstens 
nicht zu ermitteln, ob ein Nullzeiger wirklich die Adresse 0 enthält.

Autor: Andreas Schweigstill (Firma: Schweigstill IT) (schweigstill) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus schrieb:
>
> int i = 0;
> void* p = (void*)i;
> 
>
> Das ist zwar auch keine Garantie, aber man umgeht damit zumindest die
> Sonderbehandlung von 0 im Zeigerkontext. Dann braucht man wenigstens
> nicht zu ermitteln, ob ein Nullzeiger wirklich die Adresse 0 enthält.

Das ist aber wiederum gefährlich, wenn man an anderer Stelle z.B.

if (p) {
 ...
}

if (!p) {
 ...
}

if (p == NULL) {
 ...
}

verwendet. Dort wird nämlich auf die Nullzeiger-Eigenschaft überprüft
und nicht zwingend auf die Nullwert-Eigenschaft des in einen Integer
konvertierten Zeigers.

Und es dürfte in typischen Programmen deutlich mehr Stellen geben, an
denen eine Abfrage erfolgt als die explizite Zuweisung des
Nullzeigers.

Gruß
Andreas Schweigstill

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Dort wird nämlich auf die Nullzeiger-Eigenschaft überprüft
> und nicht zwingend auf die Nullwert-Eigenschaft des in einen Integer
> konvertierten Zeigers.

Wenn man einen Nullzeiger will, sollte man natürlich auch einen 
verwenden. Meine Aussage bezog sich auf den  Fall, daß man explizit 
einen Zeiger will, der die Adresse 0 enthält, z.B. weil man auf das 
zugreifen möchte, was da liegt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.