Fehler: X uninitialized kann in dieser Funktion in C verwendet werden,
-
06-07-2019 - |
Frage
Ich erhalte diese Fehler
error: Access.Core may be used uninitialized in this function
Und das ist mein Code:
static int FirstTime = 1;
MyStruct Access;
if (FirstTime) {
FirstTime = 0;
Access = Implementation();
DoSomething(Access);
}
if(Other_Variable) {
Access = Implementation2();
DoSomething(Access);
}
//The Other_Variable will be set to 1 and to 0 by other part of the code
Mein Code ist so, weil ich nur das erste Mal auf die Funktion Implementierung anrufen möge. In jedem Anruf des Access-Variable aktualisiert werden wird, so dass es sie statisch nicht viele sinnvoll machen.
Wenn ich Zugang statische Arbeiten machen, aber ich weiß nicht, wie es statisch machen, weil in jedem anderen Call-Zugang wird aktualisiert werden. Jede Art und Weise, das Problem zu vermeiden, ohne dass es statisch?.
Auch keine besseren Optionen nur einmal eine Funktion stattdessen auszuführen von einer statischen Variable sind willkommen.
Lösung
Machen Sie Access
wie diese (und entfernen FirstTime
und die if
):
static MyStruct Access = Implementation(this_b);
Der Grund, warum Sie diese Warnung erhalten, weil statische Variablen einen Funktionsaufruf zu überleben. Ihr Wert wird über alle Funktionsaufrufe beibehalten ( ohne Hinweis auf den Thread, die Funktionsaufrufe). So wird FirstTime
steuern, ob Sie Access
initialisieren. Das erste Mal, rufen Sie die Funktion, den Code in ist korrekt den Access
Variable initialisieren. Aber mit jedem weiteren Funktionsaufruf ist FirstTime
Null, und Sie werden nicht initialisieren Access
mehr, und somit wird eine nicht initialisierte Variable auf den Code verwenden.
Edit: Jetzt, mit Ihren aktualisierten Daten, Sie sagen, dass Sie zwei Implementation
Funktionen haben. Das erste Mal, wenn Sie eine verwenden möchten, und alle anderen Zeiten wollen Sie eine andere Funktion verwenden. Wie wäre es damit dann:
// static will be false/zero by default
static bool AlreadyCalled;
MyStruct Access;
if (!AlreadyCalled) {
Access = Implementation();
AlreadyCalled = true;
} else {
Access = Implementation2();
}
Je nach tatsächlichen Anwendungsfall kann es bessere Möglichkeiten, dies zu umgehen, though. Zum Beispiel, warum sich nicht um den Zustand von Access
, wie folgt aus:
// let the default constructor initialize it
// to a plausible state
static MyStruct Access;
// use RAII to update the state of Access when this
// function returns.
MyUpdater updater(Access);
// now, do whatever the function does.
So etwas wie dies für MyUpdater
:
struct MyUpdater {
MyStruct &s;
MyUpdater(MyStruct &s):s(s) { }
~MyUpdater() {
s.ChangeState();
}
};
Dieses Muster RAII
genannt wird: Sie ordnen einige nützliche Aktion mit dem Konstruktor und Destruktor eines lokal zugeordneten Objekts.
Andere Tipps
@ litb Antwort ist interessant. Ein äquivalentes Programm folgt. Der Code kompiliert und arbeitet wie in C ++ angegeben, aber nicht kompiliert in C.
#include <stdio.h>
static int newval(void) { return 3; }
void inc(void)
{
static int a = newval();
a++;
printf("%d\n", a);
}
int main(void)
{
int i;
for (i = 0; i < 10; i++)
inc();
return(0);
}
gcc sagt:
x.c: In der Funktion 'inc': x.c: 7: Fehler: initializer Element nicht konstant ist
g ++ ist ganz zufrieden damit.
Das ist ein Unterschied zwischen C und C ++, die mir nicht bewusst war (dies würde aber nicht in 300 Zeichen passen, so kann ich es nicht ein Kommentar, leicht).
@Eduardo fragte eine der Fragen in den Kommentaren: „Warum C diese und C nicht zulassen, dass ++ es zulassen?“. Da die Antwort ist mehr als 300 Zeichen ...
Wie @litb in den Kommentaren gesagt, in C können Sie nur Konstanten für initializers von statischen Variablen verwenden. Dies ist zum Teil, weil die Werte eingestellt werden, bevor main () aufgerufen wird, und es wird keine benutzerdefinierten Funktionen aufgerufen werden, bevor main () aufgerufen wird. C ++, dagegen ermöglicht globale und statische Variablen (benutzerdefiniert) Konstrukteurs initialisiert werden, bevor main () aufgerufen wird, so gibt es keinen Grund, nicht andere benutzerdefinierte Funktionen zu ermöglichen, auch genannt werden, so dass die Initialisierung ist vernünftig. Mit C89, sind Sie in dem initializers begrenzt Sie mit automatischen (lokalen) Variablen verwenden können; in C99, können Sie so ziemlich jeden Ausdruck verwenden, jeden lokalen Variable zu initialisieren.
Der Zugang ist nicht statisch, daher wird eine neue Instanz erstellt wird jedes Mal die Funktion aufgerufen wird. Nur auf der ersten Zeit zu tun, durch die Sie tatsächlich jeden Wert zuweisen; dieser Wert wird, sobald die Funktion beendet verloren.
Wenn Sie Access müssen über Aufrufe an die Funktion bestehen, machen es zu statisch.
Access
ist nicht statisch und deshalb muss es in jedem Aufruf erstellt werden.
Betrachten Sie den Code, um etwas zu vereinfachen, wie:
static MyStruct Access = Implementation(this_b);
Damit wird sichergestellt, dass die Funktion nur das erste Mal aufgerufen werden, wobei das Verfahren ausgeführt wird, und dass Access
den Wert zwischen Anrufen halten.