2017-07-19 6 views
5

Der folgende Code funktioniert:Datentyp Verwirrung in C

int main(void) 
{ 
    float f = get_float(); 
    int i = round(f*100); 
    printf("%i\n", i); 
} 

Doch Fehler generiert, wenn Codierung auf diese Weise:

printf("%i\n", round(1.21*100)); 

Output sagt round(1.21*100)float ist. Also, warum dann

int i = round(f*100); 

ist in Ordnung?

+3

Wenn ein 'float' Wert auf' int' Werte zugeordnet ist, eine interne Umwandlung stattfindet. 'round()' gibt einen doppelten Wert, wenn also keine Konvertierung durchgeführt wird, bleibt der Wert doppelt. In diesem speziellen Fall 'printf ("% i \ n ", rund (1.21 * 100));' wird keine Konvertierung durchgeführt, daher ist '% f' erforderlich, um den Gleitkommawert zu drucken. – Sma

Antwort

15

Wenn Sie

int i = round(f*100); 

tun Sie das Ergebnis der double Funktion konvertieren round. Das konvertierte Ergebnis wird in der int Variablen i gespeichert, die mit dem Format "%i" verwendet werden kann, da es ein int Argument erwartet.

Wenn Sie passieren das double Ergebnis round direkt als Argument für ein Format, das ein int Sie haben unpassendes Format und Argumenttypen erwartet. Das führt zu undefined Verhalten.

Keine Konvertierung wird in dem Aufruf von printf gemacht, und keine Umwandlung kann gemacht werden, da der Code innerhalb der printf Funktion nicht den tatsächlichen Typ des Arguments nicht kennt. Alles, was es weiß, ist das Format "%i". Alle möglichen Typinformationen gehen für Funktionen mit variablen Argumenten verloren.

+0

Nun, "keine Konvertierung vorgenommen wird", die Standard-Argument-Promotions sind dennoch getan. –

+0

@AnttiHaapala Nun, da die Funktion einen "double" -Wert zurückgibt und die Standard-Argument-Heraufstufung zu einem "double" ist, wird in diesem speziellen Fall keine Konvertierung durchgeführt. –

5

Dies ist wegen des Verhaltens von automatischen Typ Casting. In printf funktioniert die automatische Typumwandlung nicht. Wenn Sie% i sagen, erwartet es einfach Ganzzahl, es kann nicht doppelt in Ganzzahl konvertieren und dann drucken.

Im Zuweisungsvorgang wird double zuerst in Integer konvertiert und dann in den linken Operanden des Operators =. Ich hoffe das hilft.

4

Dies ist ein bisschen Vervielfältigung, aber vielleicht hilft zum besseren Verständnis:

  1. round() hat den folgenden Prototyp:

    double round(double x); 
    

    so gibt es double.

  2. Es gibt eine implizite Umwandlung vondouble zu int in C, so schreibt

    int i = round(f*100); 
    

    wird das Ergebnis zu round()int konvertieren.

  3. Wenn Sie eine Funktion haben, die ein int erwartet, z.

    void printMyNumber(int number) 
    { 
        printf("%i\n", number); 
    } 
    

    Sie können es so nennen:

    printMyNumber(round(f*100)); 
    

    und die implizite Konvertierung funktioniert wie erwartet, da die Compiler beiden Typen sehen (der Rückgabetyp von round() und die erwarteten Argumente Art von printMyNumber()).

  4. Der Grund, warum dies nicht mit printf() funktioniert, ist, dass der Prototyp printf() wie folgt aussieht:

    printf(const char *format, ...); 
    

    so, außer für das erste Argument, die Typen der Argumente sind unbekannt. Daher wird alles, was Sie übergeben, ohne Konvertierung übergeben (außer default argument promotions). Natürlich könnte man einen Guss verwenden stattdessen eine explizite Konvertierung zu erreichen:

    printf("%i\n", (int) round(f*100)); // <- this is fine