Forum: Compiler & IDEs C: Deklaration und Initialisierung


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Georg M. (g_m)


Lesenswert?

Warum dieser Behandlungsunterschied?
1
#include <avr/io.h>
2
3
uint8_t k;
4
5
int main(void)
6
{
(Alles in Ordnung)
                                                                   .
                                                                   .
                                                                   .
1
#include <avr/io.h>
2
3
int main(void)
4
{
5
  uint8_t k;
Warning:
'k' may be used uninitialized in this function [-Wmaybe-uninitialized]

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Im ersten Fall wird "k" automatisch mit 0 initialisiert, das ist für 
globale und statische Variablen vom C-Standard so vorgegeben. Lokale 
Variablen werden hingegen nicht automatisch initialisiert und 
enthalten irgendeinen Wert solange sie nicht explizit beschrieben 
werden.

: Bearbeitet durch User
von Michael B. (laberkopp)


Lesenswert?

Georg M. schrieb:
> Warum dieser Behandlungsunterschied?

Fas eone k liegt im statischen mot 0 initialisierten Speicher,

das andere k auf dem Stack und enthält in schlechten Programmen die 
Daten der  zuvor am der Stelle gespeicherten Werte der zuvor 
aufgerufenen Funktion.

von Harald K. (kirnbichler)


Lesenswert?

Michael B. schrieb:
> und enthält in schlechten Programmen

Wieso sollten das "schlechte Programme" sein? Was sollen "gute 
Programme" an dieser Stelle anders machen?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Harald K. schrieb:
> Was sollen "gute
> Programme" an dieser Stelle anders machen?

Die sollten lokale Variablen initialisieren bevor sie diese nutzen.

von Klaus K. (galaktus)


Lesenswert?

warum? Wenn sie im ersten Schritt beschrieben wird? Dann ist es doch 
wurscht

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Wenn ja, dann ja, wenn nicht, dann nicht.
Dein Code-Auschnitt ist da wenig aussagekräftig.

Die gcc-Warnung ist aber bekannt für  häufigere Fehlwarnungen.

Oliver

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Klaus K. schrieb:
> Wenn sie im ersten Schritt beschrieben wird? Dann ist es doch
> wurscht

Das geht auch, dann wird sie eben "geschrieben" statt "initialisiert" 
vor dem ersten Auslesen. Allerdings kann der Compiler das manchmal nicht 
so ganz durchblicken und gibt dann doch die Warnung aus.

Allerdings finde ich es sauberer, die Variable überhaupt erst dann zu 
deklarieren, wenn man auch einen Wert für sie hat, und sie dann eben 
damit zu initialisieren. Dann gibt es gar keinen Zeitraum, in welchem 
man die Variable versehentlich uninitialisiert nutzen kann.

von Hans-Georg L. (h-g-l)


Lesenswert?

Niklas G. schrieb:
> Harald K. schrieb:
>> Was sollen "gute
>> Programme" an dieser Stelle anders machen?
>
> Die sollten lokale Variablen initialisieren bevor sie diese nutzen.

Weil in "schlechten" Programmen die nicht initialisierte Variable z.B. 
als return zurückgegeben wird und in irgendwelchen if /else Gebirgen 
vergessen wurde ihr einen Wert zuzuweisen. Oder mit der 
uninitialisierten Variable gerechnet wird.

von Michael B. (laberkopp)


Lesenswert?

Klaus K. schrieb:
> warum

Weil das sonst ein Sicherheitsleck ist.

Findige Nutzer könnten dann zurück ermitteln welche Daten in der vorher 
aufgerufenen Funktion dort standen, vielleicht das Passwort.

Gute Programmiersprachen erlauben so einen uninitialisierten Mist gar 
nicht.

von Georg M. (g_m)


Lesenswert?

Oliver S. schrieb:
> Dein Code-Auschnitt ist da wenig aussagekräftig.

Ja, tatsächlich, die Warnung kommt erst nach "k++;", aber der Fehler ist 
"uint8_t k;".
Erst mit "uint8_t k = 0;" funktioniert das Programm richtig. Dabei gibt 
es aber nur "int main(void)", sonst nichts, keine weiteren Funktionen.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Georg M. schrieb:
> Dabei gibt
> es aber nur "int main(void)", sonst nichts, keine weiteren Funktionen.

Naja, bei
1
int main(void) {
2
  uint8_t k;
3
  k++;
4
}

Was erwartest du soll dann in k drin stehen?

von Georg M. (g_m)


Lesenswert?

Niklas G. schrieb:
> Was erwartest du soll dann in k drin stehen?

Jetzt weiß ich es nicht. Jetzt bin ich verwirrt.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Niklas G. schrieb:
> Lokale Variablen werden hingegen nicht automatisch initialisiert [...]

Zur Präzisierung: Lokale Variablen, die nicht im Static Storage liegen 
(nicht zur Speicherklasse static gehören) werden nicht automatisch 
initialisiert falls die keinen Initializer haben.

Daten im Static Storage werden immer initialisiert, egal ob lokal oder 
global, und auch dann, wenn sie keinen Initializer haben.

von Falk S. (falk_s831)


Lesenswert?

Globale Variablen bekommen halt initial nen Zustand vorgegeben, der ist 
in dem Fall 0. Funktionen, die auf diese zugreifen, sind ja immer 
irgendwo nicht reentrant, weil abhängig von etwas, was außerhalb der 
Funktion liegt (wäre bei ner lokalen static-Variable aber auch so, siehe 
GetTickCount unter Win).

Ich find's sehr begrüßenswert, dass der Compiler dich auf 
uninitialisierte Variablen hinweist - zusammen mit dem Prinzip 'Lokal 
geht vor global' könnte dann fast nen strukturiertes Programmieren mit 
definierten Funktions-Ein-/Ausgaben möglich werden :)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Niklas G. schrieb:
> Allerdings finde ich es sauberer, die Variable überhaupt erst dann zu
> deklarieren, wenn man auch einen Wert für sie hat, und sie dann eben
> damit zu initialisieren.

Hat man nicht immer. Wenn die Zuweisung beispielsweise in mehreren 
if-Zweigen erfolgt, dann hat man beim Anlegen noch keinen definierten 
Wert.

Stur einfach immer einen Initialwert reinzuknallen kann Bugs 
verschleiern, die der Compiler ohne einen solchen Initialwert (als 
Warnung) aufdecken würde.

Allerdings habe ich auch schon Situationen erlebt, in denen der Compiler 
nicht nachvollziehen konnte, dass eine Variable wirklich vor Benutzung 
auch gesetzt worden ist.

von Bruno V. (bruno_v)


Lesenswert?

Georg M. schrieb:
> Jetzt weiß ich es nicht. Jetzt bin ich verwirrt.

Dann poste halt Deinen Code. Entweder nutzt Du dort k und das Ergebnis 
ist (vermutlich) anders als erwartet. Oder Du nutzt k nicht, dann lass k 
weg.

Georg M. schrieb:
> Erst mit "uint8_t k = 0;" funktioniert das Programm richtig.
eine andere Möglichkeit ist "static uint8_t k;". Dann wird es (wie eine 
globale Variable) vor dem ersten Aufruf mit 0 initialisiert, ist aber 
nur innerhalb der {} direkt verwendbar.

Dabei gibt
> es aber nur "int main(void)", sonst nichts, keine weiteren Funktionen.
Für den C-Compiler ist main nicht unbedingt eine besondere Funktion. 
main kann prinzipiell auch mehrfach aufgerufen werden. Es ist relativ 
egal, wo Du das Konstrukt verwendest.

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.