2016-08-27 3 views
4

Im folgenden Code, die scanf() in main() dreht eine der Eingabe Zahlen von einer Zahl ungleich Null in Null, wie durch ein Debugging printf() in der While-Schleife. Ich habe es auf mehreren Compilern getestet, aber nur, um das gleiche Ergebnis zu erhalten. Bitte helfen Sie mir, indem Sie mir sagen, warum das so ist. Vielen Dank.Kann scanf() nicht-Null-Eingabe in Null drehen

#include <stdio.h> 

unsigned srl (unsigned x, int k) 
{ 
    /* perform shift arithmetically */ 
    printf("x = %u, (int) x= %d\n", x, (int) x); 
    unsigned xsra = (int) x >> k; 
    printf("\nxsra before was: %u\n", xsra); 
    unsigned test = 0xffffffff; 
    test <<= ((sizeof (int) << 3) - k); // get e.g., 0xfff00... 
    printf("test after shift is: %x, xsra & test = %x\n", test, xsra & test); 
    if (xsra & test == 0) // if xsrl is positve 
     return xsra; 
    else 
     xsra ^= test; // turn 1s into 0s 

    return xsra; 
} 

int sra (int x, int k) 
{ 
    /* perform shift logically */ 
    int xsrl = (unsigned) x >> k; 
    unsigned test = 0xffffffff; 
    test << ((sizeof (int) << 3) - k + 1); // get e.g., 0xffff00... 
    if (xsrl & test == 0) // if xsrl is positve 
     return xsrl; 
    else 
          xsrl |= test; 

     return xsrl; 
} 

int main(void) 
{ 
    int a; 
    unsigned b; 
    unsigned short n; 

    puts("Enter an integer and a positive integer (q or negative second number to quit): "); 
    while(scanf("%d%u", &a, &b) == 2 && b > 0) 
    { 
     printf("Enter the number of shifts (between 0 and %d): ", (sizeof (int) << 3) - 1); 
     scanf("%d", &n); 
     if (n < 0 || n >= ((sizeof (int)) << 3)) 
     { 
      printf("The number of shifts should be between 0 and %d.\n", ((sizeof (int)) << 3) - 1); 
      break; 
     } 
     printf("\nBefore shifting, int a = %d, unsigned b = %u\n", a, b); 
     a = sra(a, n); 
     b = srl(b, n); 
     printf("\nAfter shifting, int a = %d, unsigned b = %u\n", a, b); 
     puts("\nEnter an integer and a positive integer (q or negative second number to quit): "); 
    } 
    puts("Done!"); 

    return 0; 
} 
+2

Bezeichner für 'unsgined short' sollte'% hu' und nicht '% u' sein. – ameyCU

+0

Es wäre einfacher gewesen, wenn du mich wissen lassen würdest, welches zu 0 wird, also musste ich das Ganze nicht selbst kompilieren ... (Nun, eigentlich konnte ich es nach dem Nachladen und dem Sehen von Amey 'n' denken Kommentar.) Auch, OP, 'n' kann nie negativ sein, da es' unsigned' ist. – RastaJedi

+1

Er benutzt tatsächlich '% d', nicht'% u', für 'n', wenn auch immer noch falsch. – RastaJedi

Antwort

4

Das Problem ist, dass ein nunsigned short, die weniger Größe hat als ein normales int. Wenn Sie scanf("%d", &n); aufrufen, liest es den Wert in n und überschreibt möglicherweise den vorhandenen Wert b, wenn b den Speicherort direkt nach n hat.

Alles, was Sie tun müssen, ist, dass problematische Linie ändern in:

scanf("%hu", &n); 

die h ist ein Modifikator für unsigned short int, von here.

+2

Dies ist ein weiteres Beispiel, warum Sie immer mit "-Wall" und "-Wextra" kompilieren sollten. – RastaJedi

+0

Danke, Lyang. Ihre Antwort ist sehr hilfreich. Das stimmt, es gibt einen Überlauf wegen des falschen Eingabeformat-Spezifizierers. –

+0

Nochmals vielen Dank, RastaJedi. Ich hatte angenommen, dass die -Wall- und -Wextra-Optionen Standardwerte sind, aber es ist eigentlich kein Standard bei jedem Compiler –