mikrocontroller.net

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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Ralph S. (jjflash)


Bewertung
0 lesenswert
nicht 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):
void spgteiler_io(void)
{
  uint8_t wahl, b, dat;
  float   r1,r2, u1,u2, u;
  int     ch;

  /* ---------------------------------------------------
     Bitmuster fuer zu lesende Variable

          Bit|  7   6   5   4   3   2   1   0
     zu lesen|              R2  R1  U2  U1  U

     Beispiel Auswahl 1: U, R1 und U_R1 zu sind lesen,
     es muessen somit  Bit 0, Bit1 und Bit3 gesetzt sein
     --------------------------------------------------- */

  //                    1:U,U1,R1     2:U,R1,R2       3:U1,R1,R2
  uint8_t rflags[3] = { 0x0b,         0x19,           0x1a };


  while(keypressed()) ch= readkey();                   // Tastenpuffer loeschen
  do
  {
    clrscr();
    spgteiler_screen();

    printf("\n  Gesucht:");
    printf("\n  -------------------------\n");
    printf("\n            0: Exit\n");
    printf("\n            1: R2; U_R2");
    printf("\n            2: U_R1; U_R2");
    printf("\n            3: U\n");
    printf("\n\nEingabe: ");scanf("%d", &wahl);

    if (!wahl) return;
    if (wahl > 3) return;

    dat= rflags[wahl-1];
    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:
Eingabe: 1

 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:
  uint8_t rflags[4] = { 0x0b,         0x19,           0x1a };

dann ist die Ausgabe wie erwartet:
Eingabe: 1

 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)


Bewertung
-1 lesenswert
nicht lesenswert
Ralph S. schrieb:
> scanf("%d", &wahl);

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

leo

von foobar (Gast)


Bewertung
4 lesenswert
nicht lesenswert
Hier hapert es:
 uint8_t wahl, ...;
 ...
 scanf("%d", &wahl);

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

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


Bewertung
-1 lesenswert
nicht lesenswert
fängt der Index nixht bei 0 an ?

: Bearbeitet durch User
von Ralph S. (jjflash)


Bewertung
0 lesenswert
nicht 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:
    dat= rflags[wahl-1];

denn: 1 - 1 = 0

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

Vielen Dank an foobar

von leo (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ralph S. schrieb:
> Das ist Humbug,

Ja, ich was verwirrt wegen uint_8

leo

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht 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)


Bewertung
1 lesenswert
nicht 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:

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

von Dirk B. (dirkb2)


Bewertung
-1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Ralph S. schrieb:
> so extrem pingelig

sind Computer/Compiler doch auch.

Und man redet sonst aneinander vorbei.

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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…

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.