Forum: Offtopic Übungsblatt Informatik aus dem Studium


von Simon K. (simon) Benutzerseite


Lesenswert?

Hallöchen.

Folgende Frage finde ich auf einem Informatik-Übungsblatt aus dem 
Studium. Es geht um C.

7.) Geben Sie die Anweisung zum Einlesen einer ganzen Zahl von der 
Tastatur an. Der Zahl
soll in einer char-Variablen gespeichert werden.

Ich vermute, dass die "richtige" Antwort folgende ist (weil der Prof das 
auch in der Vorlesung schon ein mal gezeigt hat).
1
char Zahl;
2
scanf("%d", &Zahl);

Frage: Das ist doch falsch oder? Wahrscheinlich erzeugt es keine Fehler 
auf einem heutigen 32 Bit System, da die char Variable von 24 
nachfolgenden Bits auf 32Bit gepaddet wird und somit scanf die 
restlichen 3 Bytes in "toten" Speicherbereich schreibt. Aber falsch ist 
es doch trotzdem?

Folgendes Testprogramm habe ich mit Visual C++ probiert:
1
#include <stdio.h>
2
3
main()
4
{
5
  union
6
  {
7
    int A;
8
    char B;
9
  } test;
10
11
  test.A = 0xAAAAAAAA;
12
13
  scanf("%x", &test.B);
14
15
  printf("%X", test.A);
16
  getch();
17
}

Ergebnis: Wenn ich beispielsweise "CC" eingebe, gibt printf "CC" auch 
wieder aus.
Resultat: scanf schreibt 4 Byte (bei sizeof(int) == 32) an eine 
Speicherstelle, wo nur ein Byte hingehört.
Resultatsresultat:
Die (Eine) richtige Lösung ist:
1
int Temp;
2
char Zahl;
3
4
scanf("%d", Temp);
5
Zahl = Temp; /* Kein Überlaufscheck */

Oder halt über eine Union, ähnlich wie oben.

Richtig, oder Falsch? :-) Danke für eine Antwort.

PS: Die folgenden Zwei Fragen werfen ein ähnliches Problem auf:
8.) Geben Sie die Anweisung an, die den Inhalt einer char-Variablen als 
ganze Zahl im De-
zimalformat auf dem Bildschirm ausgibt.

9.) Geben Sie die Anweisung an, die den Inhalt einer char-Variablen als 
ganze Zahl im He-
xadezimalformat auf dem Bildschirm ausgibt.

von Professor (Gast)


Lesenswert?

>Richtig, oder Falsch? :-) Danke für eine Antwort.

Falsch. Bitte.

von Morin (Gast)


Lesenswert?

> Frage: Das ist doch falsch oder? Wahrscheinlich erzeugt es keine Fehler
> auf einem heutigen 32 Bit System, da die char Variable von 24
> nachfolgenden Bits auf 32Bit gepaddet wird und somit scanf die
> restlichen 3 Bytes in "toten" Speicherbereich schreibt. Aber falsch ist
> es doch trotzdem?

Es ist falsch. Ein moderner Compiler gibt eine Fehlermeldung aus, wenn 
er Spezialkenntnis über die scanf-Funktion hat (gcc zum Beispiel), 
ansonsten nicht, da der Fehler formal nicht erkennbar ist. Das mit dem 
Padding kann stimmen oder auch nicht: Der Compiler könnte zum Beispiel 
an die "toten" Stellen eine andere lokale char-Variable legen.

> Richtig, oder Falsch? :-) Danke für eine Antwort.

Fast richtig, nur ein kleiner Flüchtigkeitsfehler: scanf braucht die 
Adresse von Temp.

> PS: Die folgenden Zwei Fragen werfen ein ähnliches Problem auf:

Die gehen analog, allerdings brauchst du dafür keine lokale Variable, 
sondern kannst den Wert im printf-Aufruf direkt auf "int" casten. Ich 
meine mich sogar zu erinnern, dass bei Variabler Argumentzahl (wie bei 
scanf und printf) alle Werte automatisch auf int oder Zeiger gecastet 
werden, aber da bin ich nicht mehr sicher - mit explizitem cast bist du 
da auf der sicheren Seite und lesbarer ist es auch.

von Morin (Gast)


Lesenswert?

> Ich meine mich sogar zu erinnern, dass bei Variabler Argumentzahl (wie bei
> scanf und printf) alle Werte automatisch auf int oder Zeiger gecastet
> werden,

Nachtrag: Falls diese Vermutung stimmt, rettet es dich natürlich nur im 
printf-Fall, nicht bei scanf.

von Simon K. (simon) Benutzerseite


Lesenswert?

Morin wrote:
> Fast richtig, nur ein kleiner Flüchtigkeitsfehler: scanf braucht die
> Adresse von Temp.
Ups, ja, natürlich :D

> Die gehen analog, allerdings brauchst du dafür keine lokale Variable,
> sondern kannst den Wert im printf-Aufruf direkt auf "int" casten. Ich
> meine mich sogar zu erinnern, dass bei Variabler Argumentzahl (wie bei
> scanf und printf) alle Werte automatisch auf int oder Zeiger gecastet
> werden, aber da bin ich nicht mehr sicher - mit explizitem cast bist du
> da auf der sicheren Seite und lesbarer ist es auch.

Ah, guter Hinweis. Hier muss es also nicht zwangsläufig falsch sein. Was 
aber, wenn man einen Long-Int ausgeben will? Der wird ja dann nicht in 
int konvetiert, sonst würde es ja gar nicht funktionieren.

von Simon K. (simon) Benutzerseite


Lesenswert?

Ich habe übrigens noch mal nachgeschaut: Bei Variabler Argumentenanzahl 
benutzt man das Makro (oder Funktion, keine Ahnung)
va_arg()
Siehe:
http://www.cplusplus.com/reference/clibrary/cstdarg/va_arg.html

und hierbei gibt man an, als welchen Datentyp der Wert behandelt werden 
soll.
Sprich: Bei nur übergebenem char Datentyp, der als int behandelt wird, 
werden 3 Bytes (in meinem Falle) zu viel gelesen.

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.