Forum: PC-Programmierung unerwartetes Verhalten von printf


von Yaro (Gast)


Lesenswert?

Hallo Leute,
ich bin beim Programmieren zufällig auf folgendes Problem gestoßen:
Beim Ausführen dieses Codes
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
5
int var;
6
7
int main( ){
8
9
  printf("%f\n", 2345.0f);
10
11
  var = 6;
12
  printf("%f\n", var);
13
  printf("%i\n", var);
14
15
16
  system("PAUSE");
17
  return 0;
18
19
}
kommt das unerwartete Ergebniss: 2345 \n 2345 \n 6    raus. Eigentlich
hätte ich 2345 \n 0 \n 6   oder ähnliches erwartet.
Wie kommt soetwas?

Gruß, Yaro

von Klaus W. (mfgkw)


Lesenswert?

wieso 0?

Es hat keinen Sinn, eine int-Variable mit %f auszugeben.
Der gcc würdigt das zumindest in der Einstellung -Wall mit
einer Warnung, die du offenbar ignorierst.

Mit %i oder %d wird int ausgegeben, mit %f, %e und %g
double (bzw. float).

Alles andere ist Unfug, und jede Ausgabe nichts, was ich als
unerwartet bezeichnen würde.

von Yaro (Gast)


Lesenswert?

Es hatte Anfangs damit zutun, dass ich Probleme mit globalen und lokalen 
Variablen hatte, die ich zufällig gleich benannt habe (debug-Variablen), 
die sich dann überschatteten... Ich hab versucht das mit printf 
auszugeben und da kamen richtig verwirrende Sachen bei raus...
Wenn der Compiler mir eine Warnung angezwigt hätte, wäre es ja kein 
Problem gewesen, aber das hat er nicht (habe wohl einen zu alten (gcc))

Gruß, Yaro

von Yaro (Gast)


Lesenswert?

Scheint so, als ob das ein Problem mit meiner Programmierumgebung wäre, 
ich kriege überhaupt keine Warnungen angezeigt...

von Klaus W. (mfgkw)


Lesenswert?

1
klaus@a64a:~ > gcc -Wall t.c
2
t.c: In function ‘main’:
3
t.c:12: warning: format ‘%f’ expects type ‘double’, but argument 2 has type ‘int’
4
klaus@a64a:~ > gcc -v
5
Using built-in specs.
6
Target: i486-linux-gnu
7
Configured with: ../src/configure -v --with-pkgversion='Debian 4.3.2-1.1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-cld --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
8
Thread model: posix
9
gcc version 4.3.2 (Debian 4.3.2-1.1)

von Klaus W. (mfgkw)


Lesenswert?

Das Problem rührt daher, daß printf nicht weiß, was man ihm
übergibt - es sieht nur ein Bitmuster im Speicher und vermutet
anhand der Formatbeschreibung %f, daß es eine double ist.
Also wird das Bitmuster entsprechend ausgegeben.

Das ist etwa, als ob du einen Zeiger auf eine int hast, den
Zeiger mit einem cast zu einem Zeiger auf double vergewaltigst
und darüber aus dem Bitmuster der int eine double liest, die
dort nie stand.

von Yaro (Gast)


Lesenswert?

Das hätte dann aber nicht zufolge, dass er 2345 (das, was ich vorher 
schonmal ausgegeben hatte) ausgibt. Dann würde er mit großer 
Wahrscheinlichkeit irgendeine andere Zahl, oder NaN ausgeben.
Scheint, dass das in der Funktion selber irgendwie anders gehandhabt 
wird.

Gruß, Yaro

von Klaus W. (mfgkw)


Lesenswert?

Das kann auch einfach daran liegen, daß ein float- bzw.
double-Parameter anders übergeben wird als eine int; z.B.
in einem FPU-Register (je nach Compiler).
Bei dem zweiten Aufruf mit der int wird das FPU-Register
dann nicht verändert und der Wert vom ersten Aufruf liegt
da noch.
Müsste man halt mal den erzeugten Maschinencode anschauen,
wenn es dich interessiert.

Sonderlich wichtig finde ich es aber eigentlich nicht,
weil es einfach falscher Quelltext ist und der je nach
Rechner und Compiler beliebigen Schwachsinn produzieren
darf.

von Yaro (Gast)


Lesenswert?

So ähnlich wird es wohl sein.
Sich den erzeugten Code von printf anzuschauen sollte relativ 
kompliziert werden, da printf relativ unübersichtlich (schon in C) 
geschrieben ist.
Ich habe jetzt die Warnungen auch angeschaltet und sollte damit dann 
keine größeren Probleme mehr bekommen.

Danke für deine Hilfe!
Gruß, Yaro

von Klaus W. (mfgkw)


Lesenswert?

Bitte.

Du musst ja nicht den Code von printf anschauen, es reicht
der Aufruf in deinem Quelltext. Dazu habe ich aber heute auch
keine Lust, mehr ich habe noch Hunger.

von D. I. (Gast)


Lesenswert?

Yaro schrieb:
> Es hatte Anfangs damit zutun, dass ich Probleme mit globalen und lokalen
> Variablen hatte, die ich zufällig gleich benannt habe (debug-Variablen),
> die sich dann überschatteten... Ich hab versucht das mit printf
> auszugeben und da kamen richtig verwirrende Sachen bei raus...
> Wenn der Compiler mir eine Warnung angezwigt hätte, wäre es ja kein
> Problem gewesen, aber das hat er nicht (habe wohl einen zu alten (gcc))
>
> Gruß, Yaro

ich meine dafür gibt es -Wshadow dann wird dir das angezeigt, jedenfalls 
gibts ein flag dafür

von Yaro (Gast)


Lesenswert?

Habs jetzt auch gefunden, mache das nun mit -Wall

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.