webentwicklung-frage-antwort-db.com.de

Bei -1 beginnende Schleife gibt nichts aus

Dieses Programm soll die Elemente von array ausdrucken, aber wenn es ausgeführt wird, wird keine Ausgabe angezeigt.

#include <stdio.h>

#define TOTAL_ELEMENTS  (sizeof(array) / sizeof(array[0]))

int array[] = { 23, 34, 12, 17, 204, 99, 16 };

int main() {
    int d;
    for (d = -1; d <= (TOTAL_ELEMENTS - 2); d++) 
        printf("%d\n", array[d + 1]);
    return 0;
}

Warum zeigt dieses Programm keine Ausgabe an?

55
rohit kumar

sizeof gibt eine vorzeichenlose Ganzzahl zurück, daher ist TOTAL_ELEMENTS auch vorzeichenlos.

d ist signiert. Anfangs ist d-1. Wenn der Vergleich durchgeführt wird, wird d implizit als vorzeichenlos typisiert, sodass es nicht mehr -1 Ist, wenn es mit TOTAL_ELEMENTS Verglichen wird, sondern tatsächlich UINT_MAX. (Dies ist 4294967295 auf meinem Computer, kann sich jedoch für andere unterscheiden.).

Ebenfalls,

Wenn Sie dies beheben möchten, tippen Sie TOTAL_ELEMENTS In int:

for(d = -1; d <= (int)(TOTAL_ELEMENTS - 2); d++) 

Dies wird drucken:

23
34
12
17
204
99
16

Wie Sie es erwarten würden. Vielleicht möchten Sie auch Vergleichsoperation für vorzeichenlose und vorzeichenlose Ganzzahlen ansehen, um weitere Informationen zum Thema vorzeichenlose Vergleiche zu erhalten.

Es ist erwähnenswert, dass das Aktivieren von Compiler-Warnungen Ihnen geholfen hätte, herauszufinden, was los war (wie von Hyde in seinem Kommentar ):

$ gcc -Wall -Wextra test.c
test.c:7:17: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
      for(d = 0; d < TOTAL_ELEMENTS; d++) 
              ~ ^ ~~~~~~~~~~~~~~
1 warning generated.

Alternativ können Sie d auch bei 0 Starten und stattdessen zu TOTAL_ELEMENTS - 1 Ausführen. Sie können sogar den Typecast ablegen, der nur für den Eckfall d = -1 Erforderlich ist.

for(d = 0; d < TOTAL_ELEMENTS; d++) 
    printf("%d\n", array[d]);

Als Fußnote hier die relevanten C99 Standard-Auszüge:

  1. 6.3.1.8p2 definiert die Konvertierung von einem vorzeichenbehafteten in einen vorzeichenlosen Typ.

    Wenn der Operand mit dem vorzeichenlosen Integer-Typ einen Rang hat, der größer oder gleich dem Rang des Typs des anderen Operanden ist, wird der Operand mit dem vorzeichenlosen Integer-Typ in den Typ des Operanden mit dem vorzeichenlosen Integer-Typ konvertiert.

  2. 6.3.1.3p2 definiert, wie die Konvertierung durchgeführt wird: Durch Hinzufügen von UINT_MAX + 1 Zur signierten Darstellung.

    Wenn der neue Typ kein Vorzeichen hat, wird der Wert konvertiert, indem wiederholt ein Wert mehr als der Maximalwert, der im neuen Typ dargestellt werden kann, addiert oder subtrahiert wird, bis der Wert im Bereich des neuen Typs liegt.

    Also -1 => -1 + (UINT_MAX + 1) = UINT_MAX Für dieses Szenario.

155
cs95

Mein gcc gibt diese Warnung aus:

warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
      for(d = 0; d < TOTAL_ELEMENTS; d++) 

was bedeutet, dass (TOTAL_ELEMENTS-2)unsigned int ist, während dsigned int ist. Dies bewirkt, dass der Ausdruck immer false für den Anfangswert von d ist, da (unsigned int)(-1) > (TOTAL_ELEMENTS-2).

39
CIsForCookies

Binäre Operationen zwischen verschiedenen Integraltypen werden innerhalb eines "gemeinsamen" Typs ausgeführt, der durch sogenannte übliche arithmetische Umwandlungen definiert ist. Int d ist also vom Typ singed, der mit dem Wert -1 initialisiert wurde. Bei der Konvertierung in ein vorzeichenloses int wird das Maximum des vorzeichenlosen int zurückgegeben, das viel größer ist als der von TOTAL_ELEMENTS zurückgegebene Wert.

5
Patt