Forum: PC-Programmierung Merkwürdiges Array mit 32-Bit GCC (Linux)


von Ralph S. (jjflash)


Lesenswert?

Ausgangssituation:

Aufgabenstellung für Auszubildenden ist Berechnung eines 
Spannungsteilers mit C.

System:   Slackware-Linux 32-Bit
Compiler: GCC 5.3.0
Ausgabe: Console.

Er wollte über Bitmuster in einem Array entscheiden, welche Variable 
eingelesen werden müssen.

Mit folgendem kam er zu mir (und ich hatte mich gefreut dass da 
Engagement vorhanden ist, die letzte printf-Zeile war für ihn zum 
Fehlersuchen):
1
void spgteiler_io(void)
2
{
3
  uint8_t wahl, b, dat;
4
  float   r1,r2, u1,u2, u;
5
  int     ch;
6
7
  /* ---------------------------------------------------
8
     Bitmuster fuer zu lesende Variable
9
10
          Bit|  7   6   5   4   3   2   1   0
11
     zu lesen|              R2  R1  U2  U1  U
12
13
     Beispiel Auswahl 1: U, R1 und U_R1 zu sind lesen,
14
     es muessen somit  Bit 0, Bit1 und Bit3 gesetzt sein
15
     --------------------------------------------------- */
16
17
  //                    1:U,U1,R1     2:U,R1,R2       3:U1,R1,R2
18
  uint8_t rflags[3] = { 0x0b,         0x19,           0x1a };
19
20
21
  while(keypressed()) ch= readkey();                   // Tastenpuffer loeschen
22
  do
23
  {
24
    clrscr();
25
    spgteiler_screen();
26
27
    printf("\n  Gesucht:");
28
    printf("\n  -------------------------\n");
29
    printf("\n            0: Exit\n");
30
    printf("\n            1: R2; U_R2");
31
    printf("\n            2: U_R1; U_R2");
32
    printf("\n            3: U\n");
33
    printf("\n\nEingabe: ");scanf("%d", &wahl);
34
35
    if (!wahl) return;
36
    if (wahl > 3) return;
37
38
    dat= rflags[wahl-1];
39
    printf("\n wahl: %d ; rflags[wahl]: 0x%.2x ; rflags[0]: 0x%.2x", wahl, dat, rflags[0]);

Die Ausgabe der printf-Zeile (bei einer Eingabe 1) ist:
1
Eingabe: 1
2
3
 wahl: 1 ; rflags[wahl]: 0x00 ; rflags[0]: 0x0b

Er (und ich auch) hätte für rflags[wahl] den Wert 0x0b erwartet!

Ändert man das Array rflags nach:
1
  uint8_t rflags[4] = { 0x0b,         0x19,           0x1a };

dann ist die Ausgabe wie erwartet:
1
Eingabe: 1
2
3
 wahl: 1 ; rflags[wahl]: 0x0b ; rflags[0]: 0x0b

!!!!!

Kann das daran liegen, dass diese 3 unsigned Bytes nicht einmal einem 
ganzen Integer (32-Bit = 4 Byte) entspricht und die Adressierung 
irgendwo "klemmt" oder ist das ein reguläres Verhalten und ich übersehe 
etwas.

Wie gesagt, das Problem ist ja gelöst, aber ich wüsste gerne woran das 
liegt.

Wird nach der gleichen Methode eine Auswahl der einzulesenden Variable 
vorgenommen und es existieren bspw. 9 Bytes, dann zeigt ein

uint8_t rflags[9]

nicht das "fehlerhafte" Verhalten von

uint8_t rflags[3]

-----------------------------------------------

Irgendwie mag ich nicht glauben, dass ich einem Fehler von GCC auf die 
Spur gekommen bin und werde mal sehen, wie sich das zum einen auf einem 
64-Bit System und zum anderen mit einer neueren Compilerversion verhält. 
Vielleicht aber hat jemand von Euch eine Erklärung für mich !

Ein schönes Wochenende,

JJ

von leo (Gast)


Lesenswert?

Ralph S. schrieb:
> scanf("%d", &wahl);

ASCII '0' .. '9' ist nicht gleich Zahl 0 .. 9.

leo

von foobar (Gast)


Lesenswert?

Hier hapert es:
1
 uint8_t wahl, ...;
2
 ...
3
 scanf("%d", &wahl);

Der scanf erwartet einen int-Pointer und schreibt auch ein int (4 
Bytes).

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

fängt der Index nixht bei 0 an ?

: Bearbeitet durch User
von Ralph S. (jjflash)


Lesenswert?

leo schrieb:
> Ralph S. schrieb:
>> scanf("%d", &wahl);
>
> ASCII '0' .. '9' ist nicht gleich Zahl 0 .. 9.
>
> leo

Das ist Humbug, %d liest eine Zahl und keinen ASCII ein (allerdings - 
und logischerweise - wie wir am Beitrag von foobar sehen, einen 4-Byte 
Wert, der fälschlicherweise einem unsigned char zugeordnet wurde).

foobar schrieb:
> Hier hapert es: uint8_t wahl, ...;
>  ...
>  scanf("%d", &wahl);
>
> Der scanf erwartet einen int-Pointer und schreibt auch ein int (4
> Bytes).

Das hier ist die richtige Antwort (und mir auf den Kopf haue)

Joachim D. schrieb:
> fängt der Index nixht bei 0 an ?

schon, deswegen steht dort ja auch:
1
    dat= rflags[wahl-1];

denn: 1 - 1 = 0

--------------------------------------------------

Vielen Dank an foobar

von leo (Gast)


Lesenswert?

Ralph S. schrieb:
> Das ist Humbug,

Ja, ich was verwirrt wegen uint_8

leo

von Dirk B. (dirkb2)


Lesenswert?

Was foobar schreibt.

Da sollte der Compiler aber eine Warnung raus hauen.

Er muss so eingestellt werden, dass er das macht.

In stdint.h sind auch die Formatspecifier der Typen für scanf mit 
definiert.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Dirk B. schrieb:
> Da sollte der Compiler aber eine Warnung raus hauen.

Das tut er mit -Wall oder -Wformat auch, sogar sehr ausführlich:

1
test.c:33:37: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘uint8_t *’ {aka ‘unsigned char *’} [-Wformat=]
2
   33 |     printf("\n\nEingabe: ");scanf("%d", &wahl);
3
      |                                    ~^   ~~~~~
4
      |                                     |   |
5
      |                                     |   uint8_t * {aka unsigned char *}
6
      |                                     int *
7
      |                                    %hhd

von Dirk B. (dirkb2)


Lesenswert?

Yalu X. schrieb:
> Das tut er mit -Wall oder -Wformat auch, sogar sehr ausführlich:

Das war der Hinweis, die Warnungen zu aktivieren und dann auch zu 
beachten.

"Sind ja nur Warnungen. Egal, die EXE hat er ja gemacht."

von Ralph S. (jjflash)


Lesenswert?

Smile, die Warnungen hat er auch ausgegeben... allerdings (Asche auf 
mein Haupt) waren die Warnungen weit oberhalb der nachfolgenden 
Compilermeldungen anderer eingebundener Sourcen und nicht zu sehen und 
ich habs bei der Durchsicht auf dem Ausbildungsrechner nicht bemerkt.

Im übrigen gebe ich der Einfachkeit wegen die Programmierübungen auf 
einem Linuxsystem aus und vin daher wird keine .exe erzeugt.

Aaaber, foobar hats gefunden (und der Compiler auch)... und wer lesen 
kann ist klar im Vorteil

von Dirk B. (dirkb2)


Lesenswert?

Ralph S. schrieb:
> daher wird keine .exe erzeugt.

Das EXE ist als Kurzform für Executable gemeint.

DOS (und auch Windows) benötigen das .exe als Dateinamenerweiterung.

 *ix Systeme benötigen diese Kennzeichnung nicht. Dennoch bleibt es eine 
EXE ?


Wird am Ende keine Erfolgsmeldung (1 Warnung, 0 Fehler) mehr ausgegeben?

von Walter K. (walter_k488)


Lesenswert?

Dirk B. schrieb:
> *ix Systeme benötigen diese Kennzeichnung nicht. Dennoch bleibt es eine
> EXE ?

das stand aber im Kontext zu "... die 'EXE' hat er(der gcc) ja 
gemacht..." -
und das ist zumindest missverständlich, denn executables entstehen durch 
das das setzen des X-Bits ... und sind keine Aufgaben des `Compilers 
oder Linkers

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Walter K. schrieb:
> und das ist zumindest missverständlich, denn executables entstehen durch
> das das setzen des X-Bits ...

Das gibt nur das Recht zur Ausführung.
Kann ich einem Bild (jpg) auch geben, bringt aber nichts.

> ... und sind keine Aufgaben des `Compilers
> oder Linkers

Die machen die technische Seite (für Binaries)

von Ralph S. (jjflash)


Lesenswert?

... unglaublich....

Ich kenne kein anderes Forum als das hier (egal welches Fachgebiet), wo 
es so extrem pingelig ist wie hier

von Dirk B. (dirkb2)


Lesenswert?

Ralph S. schrieb:
> so extrem pingelig

sind Computer/Compiler doch auch.

Und man redet sonst aneinander vorbei.

von Rolf M. (rmagnus)


Lesenswert?

Ralph S. schrieb:
> Ich kenne kein anderes Forum als das hier (egal welches Fachgebiet), wo
> es so extrem pingelig ist wie hier

Aber du hast das doch selbst durch eigene Pingeligkeit angestoßen:

Dirk B. schrieb:
> "Sind ja nur Warnungen. Egal, die EXE hat er ja gemacht."

Ralph S. schrieb:
> Im übrigen gebe ich der Einfachkeit wegen die Programmierübungen auf
> einem Linuxsystem aus und vin daher wird keine .exe erzeugt.

Ob das jetzt eine .exe-Datei ist oder nicht, spielt doch gar keine 
Rolle. Es ging lediglich darum, dass man Warnungen nicht ignorieren 
sollte.

: Bearbeitet durch User
von Ralph S. (jjflash)


Lesenswert?

Rolf M. schrieb:
> Ob das jetzt eine .exe-Datei ist oder nicht, spielt doch gar keine
> Rolle. Es ging lediglich darum, dass man Warnungen nicht ignorieren
> sollte.

Warnungen sollte man nie ignorieren, deswegen ja auch "Asche über mein 
Haupt". Zudem war das ja "nur" ein Code bei dem ich den Fehler gesucht 
habe und der nicht von mir war (der mir aber hätte auch passieren 
können).

Schlicht weil in Verbindung mit 8-Bit Controllern eine Variable 
(zumindest bei mir) häufiger uint8_t ist.

Wobei: Selbst auf einem 8-Bit System (jetzt aus dem hohlen Bauch heraus) 
würde ein

scanf("%d", &wahl);

einen Zeiger auf einen 16-Bit Integer zurück liefern.

Schmunzeln muss: Mit "pingelig" meinte ich, was für eine 
Threadverlängerung hier eintritt nachdem die Erklärung bereits geliefert 
worden ist.

Ich arbeite mit einem eigenen Konsoleneditor und bin jetzt am überlegen, 
wie ich eventuell einen Browser für Compilerwarnungen realisieren 
könnte.

Im Moment sieht es so aus, dass es am unteren Bildschirmrand einen 
Ausgabe der Compilermeldungen gibt und, wenn dieses zu klein eingestellt 
ist man nicht sieht, dass es Warnungen gegeben hat. Ich hätte schlicht 
dieses Fenster scrollen sollen und dann wäre mir das wahrscheinlich 
(sagen wir zu 90%) aufgefallen.

Allerdings muß ich auch sagen, dass ich beeindruckt bin, wie schnell 
manche (hier war es foobar) Programmcodes analysieren und das Falsche 
sehen (und ich dachte schon, ich wäre darin gut).

Dass eine Variable den falschen Typ hat habe ich in diesem Fall schlicht 
übersehen (und schlichtweg deshalb, weil ich ansonsten mit eigenen 
Eingaberoutinen und nicht mit scanf arbeite).

von Uhu U. (uhu)


Lesenswert?

Ralph S. schrieb:
> Ich arbeite mit einem eigenen Konsoleneditor und bin jetzt am überlegen,
> wie ich eventuell einen Browser für Compilerwarnungen realisieren
> könnte.

Selbsterfundene Räder rollen einfach besser…

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.