2012-08-03 9 views
10

Ich entferne GCC-Warnungen von einem Legacy-Code.Wie zu beheben: "Casse zu Zeiger aus Integer unterschiedlicher Größe" Warnung in C-Code?

Ist es möglich, die Warnung „zu gieße Zeiger von Ganzzahl von unterschiedlicher Größe“ durch eine Schublade gesteckt zu unterdrücken:

example: 

some_struct *ptr = func() // func() returns an integer. 

Kann jemand bitte leite mich, wie zu lösen solche gcc Warnungen?

+7

Warum möchten Sie eine Ganzzahl in einen Struct-Zeiger einfügen? – Jay

+0

Es ist möglich, aber die Fälle, in denen das der richtige Weg ist, sind selten. –

+0

Überlastung der "Ausgabe" -Differenzen (nicht die Eingabeparameter) –

Antwort

19

Erstens, wenn Sie func beheben können (darf seine Quelle ändern), dann reparieren Sie es. Wenn seine Berechnungen mit Zeigern durchgeführt werden können, dann machen Sie sie mit Zeigern und Zeigern zurück. Manchmal gibt es gute Gründe, mit Adressen als ganze Zahlen zu arbeiten (z. B. mit Ausrichtungsproblemen in einem speziellen Code umzugehen). Ändern Sie in diesem Fall func, um den Typ uintptr_t (definiert in stdint.h) zu verwenden. Es ist für die Behandlung von Zeigern als ganze Zahlen ausgelegt, wenn dies erforderlich ist. (Es gibt auch intptr_t, wenn arithmetische Vorzeichen aus irgendeinem Grund besser sind, aber ich finde im Allgemeinen die unsignierte uintptr_t weniger problematisch.) Vorzugsweise sollte func die uintptr_t in einen Zeiger bei der Rückgabe konvertieren, so würde der Rückgabetyp von func ein Zeiger sein (auf etwas, vielleicht some_struct oder void).

Wenn Sie func nicht beheben können, können Sie mithilfe von Umwandlungen dem Compiler mitteilen, dass Sie die ausgeführten Konvertierungen ausführen möchten. Diese spezielle Fehlermeldung sagt Ihnen jedoch, dass Sie nicht nur eine ganze Zahl in einen Zeiger konvertieren, sondern dass Sie eine Ganzzahl einer Größe (z. B. vier Bytes) in einen Zeiger einer anderen Größe (z. B. acht Bytes) konvertieren. Es ist wahrscheinlich, dass dieser Code ursprünglich für ein System geschrieben wurde, in dem der von func zurückgegebene Integer-Typ die gleiche Größe wie der Zeigertyp hatte, aber jetzt auf einem System kompiliert, bei dem der Zeigertyp größer oder kleiner als diese Ganzzahlgröße ist.

In diesem Fall müssen Sie sicherstellen, dass die von func ausgeführte Berechnung in der neuen Architektur funktioniert. Wenn nur ein 32-Bit-Wert zurückgegeben wird, wird dieser immer den richtigen Wert enthalten? Das heißt, nichts wird durch die fehlenden hohen 32 Bits verloren gehen? Keine Adresse, die func sollte jemals den Maximalwert des Integer-Typs, den es verwendet, berechnen? Wenn func vorzeichenbehaftete Integer-Typen verwendet, berücksichtigen Sie auch das Vorzeichen-Bit. Wenn Sie sichergestellt haben, dass der von func zurückgegebene Wert korrekt ist, können Sie explizite Umwandlungen verwenden, beispielsweise: some_struct *ptr = (some_struct *) (intptr_t) func();.

6

Mein gcc gibt nicht die Warnung, die Sie zitiert haben. Es wäre auch seltsam, weil es in Ihrem Code keine Besetzung gibt.

Ich erhalte die Warnung

assignment makes pointer from integer without a cast 

Notiere die "ohne Guss" -Teil. So können Sie schweigen machen gcc durch Gießen (ohne das Verhalten zu ändern):

some_struct *ptr = (void*)func(); 

Dann werden Sie Ihre Warnung erhalten („cast Zeiger von Ganzzahl von unterschiedlicher Größe“) genau dann, wenn der Rückgabetyp func nicht passen für Adressen. Dies kann durch zusätzliches Gießen von func() auf einen geeigneten ganzzahligen Typ, z. intptr_t:

some_struct *ptr = (void*)(intptr_t)func(); 

All dies unter der Annahme, Sie wirklich den falschen Glanz und Größe Ganzzahl in einen Zeiger umwandeln möchten. Wahrscheinlich ist eine Überarbeitung des Codes eine bessere Idee.

3

Es gibt zwei Möglichkeiten:

  1. func einen tatsächlichen Zeiger auf eine ganze Zahl werfen; es wird später als Zeiger verwendet.
  2. func gibt eine ganze Zahl zurück, die in einem Zeiger gespeichert wird; ptr wird später in eine Ganzzahl umgewandelt und als Ganzzahl verwendet.

Im ersten Fall wird der Rückgabewert von func wird Informationen, verlieren und möglicherweise zum Absturz bringen oder noch schlimmer, wenn int kleiner als die Größe eines Datenzeiger ist, die es auf den meisten 64-bit memory models (einschließlich sein wird Windows und Linux). In diesem Fall sollten Sie den Rückgabetyp von func zu intptr_t ändern; siehe Using intptr_t instead of void*? und Why/when to use `intptr_t` for type-casting in C?.

Im zweiten Fall ist es weniger ein Problem, sondern Endlichkeitsprobleme zu behandeln, die Sie durch intptr_t: some_struct *ptr = (some_struct *)(intptr_t)func(); und später int value = (int)(intptr_t)ptr; werfen sollten. Eine Erörterung des Problems finden Sie unter GLib Type Conversion Macros.