Forum: Mikrocontroller und Digitale Elektronik AVR C implizite Typkonvertierung, fehlerträchtig oder falsch?


von DerAltePete (Gast)


Lesenswert?


von DerAltePete (Gast)


Lesenswert?


von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Welchen Typ hat der Rückgabewert Deiner Funktion millis?

von Peter D. (peda)


Lesenswert?

DerAltePete schrieb:
> liefert eine Warnung

Und deren Wortlaut ist?

von DerAltePete (Gast)


Lesenswert?

Danke für den Tip. Ich dachte millis() ist bekannt, aber woher denn 
auch?!

Es gelingt mir allerdings nicht, eine Pseudo-millis() zu definieren, die 
unsigned long liefert, so dass das Gesamtergebnis stimmt.

von C-Frickler (Gast)


Lesenswert?

DerAltePete schrieb:

> Aber
>
1
> unsigned short setup() {
2
>         return millis() >> 16;
3
> }
4
>
> liefert eine Warnung und wird zu

Die Warnung hättest du ruhig mal im Posting nennen können: millis() ist 
nicht deklariert. Der Compiler wird daher annehmen, dass es einen int 
zurückliefert und da der auf AVR nur 16 Bit breit ist, schiebst du den 
Wert komplett raus und bekommst als Rückgabewert nur noch 0 oder -1 je 
nach Vorzeichen.

> Kann jemand dieses Verhalten logisch erklären und die Zeile mit Shift in
> C so formulieren, dass das Erwartete herauskommt?

Das Problem ist erstmal nicht die Zeile mit dem Shift, sondern die 
fehlende Deklaration von millis().

von (prx) A. K. (prx)


Lesenswert?

DerAltePete schrieb:
>         lsl r25
>         sbc r24,r24
>         mov r25,r24
>
> Kann jemand dieses Verhalten logisch erklären und die Zeile mit Shift in
> C so formulieren, dass das Erwartete herauskommt?

r25:r24 = (r25 < 0) : -1 : 0.

Das kommt raus, wenn du eine 16-Bit Integer mit Vorzeichen durch 65536 
dividierst. Ausser dem Vorzeichen bleibt nichts mehr übrig.

: Bearbeitet durch User
von DerAltePete (Gast)


Lesenswert?

Danke A. K. und C-Frickler, völlig richtig und auf der blöden falschen 
Annahme von mir basierend, dass "unsigned long millis()" bekannt sein 
müßte, was es natürlich nicht ist.

Aber mit meinen Versuchen, eine Pseudo-"unsigned long millis()" zu 
definieren, so dass ich den Assembler-Code testen kann, bin ich bisher 
im Godbolt gescheitert. Vielleicht helft Ihr kurz?

von (prx) A. K. (prx)


Lesenswert?

Peter D. schrieb:
>> liefert eine Warnung
>
> Und deren Wortlaut ist?

Ich tippe auf sowas wie "Missing declaration". Bei millis kommt 
eigentlich "unsigned long" raus, aber ohne Deklaration geht der Compiler 
von "int" aus.

von C-Frickler (Gast)


Lesenswert?

DerAltePete schrieb:

> Aber mit meinen Versuchen, eine Pseudo-"unsigned long millis()" zu
> definieren, so dass ich den Assembler-Code testen kann, bin ich bisher
> im Godbolt gescheitert. Vielleicht helft Ihr kurz?

"unsigned long millis();" wäre die einfachste Möglichkeit, wenn dem 
Compiler der Funktionsinhalt unbekannt sein soll.

Ansonsten halt wie im ersten Link mit einem "return timer;" drin und 
geeigneter Definition von timer?

Es wäre einfacher dir zu helfen, wenn du mal erklären würdest warum du 
den Assemblercode anschaust und was das dahinterstehende Problem ist.

von Axel S. (a-za-z0-9)


Lesenswert?

C-Frickler schrieb:
> Es wäre einfacher dir zu helfen, wenn du mal erklären würdest warum du
> den Assemblercode anschaust und was das dahinterstehende Problem ist.

Das "Problem" ist Größenwahnsinn bzw. mindestens Überheblichkeit, die 
ihn den Fehler beim Compiler suchen läßt. Statt vor dem Bildschirm, wo 
er mit 99% Wahrscheinlichkeit zu finden wäre.

von DerAltePete (Gast)


Lesenswert?

Kein Fehler im Programm, pures Interesse, was der Compiler aus dem 
C-Code macht, weil ich durch einen Post hier das Tool von Godbolt 
entdecken durfte.

Nun tu ich mich aber zunächst schwer, es korrekt in Betrieb zu nehmen.

Deswegen hatte ich um Anschubförderung gebeten und keine bösartigen 
Unterstellungen erwartet.

von Oliver S. (oliverso)


Lesenswert?

godbolt musst du nicht in Betrieb nehmen, weder korrekt noch sonstwie. 
Das macht der Betreiber für dich.

Ansonsten ist das, wie auch alle Compiler, ein SiSo-Tool. Shit in, shit 
out.

Oliver

: Bearbeitet durch User
von DerAltePete (Gast)


Lesenswert?


von Theor (Gast)


Lesenswert?

@ DerAltePete

Du solltest Dir klarmachen, dass Compiler Werkzeuge sind, auf deren 
korrekter Funktion sich eine sehr große Anzahl Softwareentwickler 
verlassen und verlassen müssen. So ein Fehler (in so einem grundlegenden 
Zusammenhang) wäre ein ernsthaftes Alarmzeichen! Ungefähr wie in einem 
überfüllten Raum "Feuer" rufen!

Kurz: Bitte sei sehr sorgfältig und gewissenhaft, mit solchen Aussagen 
bzw. Fragen. Es ist zwar möglich und schon vorgekommen, aber äusserst 
unwahrscheinlich, dass Fehler in eher simplen Zusammenhängen in 
Compilern auftreten.

von DerAltePete (Gast)


Lesenswert?


Beitrag #5654368 wurde vom Autor gelöscht.
von Theor (Gast)


Lesenswert?

DerAltePete schrieb:
> Hier einer meiner Versuche, der einfach zeigt, dass der Compiler
> wenigstens merkwürdige Dinge tut:

Ja ja. Suprafluide Substanzen sind auch merkwürdig.

von DerAltePete (Gast)


Lesenswert?


von (prx) A. K. (prx)


Lesenswert?

DerAltePete schrieb:
> Hier einer meiner Versuche, der einfach zeigt, dass der Compiler
> wenigstens merkwürdige Dinge tut:

Wenn der Compiler die Wahl hat, das zu tun was du sagst, und das zu tun 
was du meinst, entscheidet er sich eigentlich immer für Ersteres.

von Nico W. (nico_w)


Lesenswert?

Wo ist denn das Problem das Millis aus meinem Beispiel zu übernehmen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

DerAltePete schrieb:
> Danke für den Tip. Ich dachte millis() ist bekannt, aber woher denn
> auch?!

Willst Du, daß man Dir bei Deinem Problem hift?

Ich benutze nicht Deinen Programmcode und Dein Entwicklungssystem, aber 
ich finde, daß Du auf meine Frage Dir die geschätzt 30 Sekunden Zeit 
spendieren können solltest, die Antwort herauszufinden und zu posten.

Ich bin mir recht sicher, daß Dein Problem genau damit zu tun haben 
wird, und genau deswegen habe ich Dir die Frage gestellt.

von Axel S. (a-za-z0-9)


Lesenswert?

DerAltePete schrieb:
> mit meinen Versuchen, eine Pseudo-"unsigned long millis()" zu
> definieren, so dass ich den Assembler-Code testen kann, bin ich bisher
> im Godbolt gescheitert

Ernsthaft?

1
unsigned long millis();
2
3
unsigned short setup() {
4
        return millis() >> 16;
5
}
Das war dir zu schwierig? Eventuell willst du ja auch nochmal den 
Unterschied zwischen Deklaration und Definition in C nachlesen.


DerAltePete schrieb:
> Hier einer meiner Versuche, der einfach zeigt, dass der Compiler
> wenigstens merkwürdige Dinge tut

Merkwürdigkeit liegt im Auge des Betrachters. Der Compiler tut schon das 
Richtige. Nur gilt eben: garbage in - garbage out. Auch der beste Koch 
kann aus ScheiXXe kein wohlschmeckendes Kompott zaubern.

: Bearbeitet durch User
von Eric B. (beric)


Lesenswert?

Axel S. schrieb:
> Ernsthaft?

Je nachdem wie man millis() in Godbolt definiert, declariert oder 
implementiert, und welche Optimierungsoptionen man einstellt, ändert 
sich auch der generierte Code von "setup". Für Menschen die den AVR 
nicht von innen und aussen kennen, kann das schon für Verwirrung sorgen.
1
unsigned long millis() {
2
  // Damit millis() nichts konstantes zurückliefert
3
  // und nicht wegoptimiert werden kann
4
  static long x;
5
  return ++x;
6
}
7
8
unsigned short setup() {
9
        return millis() >> 16;
10
}

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Eric B. schrieb:
> unsigned long millis() {
>   // Damit millis() nichts konstantes zurückliefert

So gehts einfacher: extern unsigned long millis(void);

Generell würde ich in C von f() abraten, f(void) ist besser.

von Axel S. (a-za-z0-9)


Lesenswert?

Eric B. schrieb:
>
> Je nachdem wie man millis() in Godbolt definiert, declariert oder
> implementiert, und welche Optimierungsoptionen man einstellt, ändert
> sich auch der generierte Code von "setup".

Jein. So lange millis() in der aktuellen Übersetzungseinheit lediglich 
deklariert, aber nicht definiert ist, hat der Compiler keine andere 
Option, als einen rcall zu millis() zu generieren und dann das Ergebnis 
wie gefordert zu manipulieren. Was - aufgrund des avr-gcc ABI [1] - auf 
eine Nulloperation hinausläuft. Denn millis() liefert sein unsigned long 
Resultat in R25..R22 zurück mit dem MSB in R25. setup() liefert sein 
unsigned int Resultat in R25:R24 zurück, was erfreulicherweise schon 
genau die gewünschten beiden höherwertigen Bytes des Rückgabewerts von 
millis() enthält. Sowohl die Schiebeoperation als auch die Division 
durch 65536 optimiert der Compiler zu - nichts. In jeder 
Optimierungsstufe außer O0 - da kopiert er die Daten ein bißchen im 
Kreis herum.

> Für Menschen die den AVR nicht von innen und aussen kennen, kann
> das schon für Verwirrung sorgen.

Wenn man den Anspruch hat, den von avr-gcc generierten Code verstehen 
und gar dessen Korrektheit oder Qualität beurteilen zu wollen, dann 
muß man mindestens die Aufrufkonventionen des Compilers kennen.


[1] https://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage

von DerAltePete (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Welchen Typ hat der Rückgabewert Deiner Funktion millis?

DerAltePete schrieb:
> Danke für den Tip. Ich dachte millis() ist bekannt, aber woher
> denn
> auch?!

Rufus Τ. F. schrieb:
> Ich bin mir recht sicher, daß Dein Problem genau damit zu tun haben
> wird, und genau deswegen habe ich Dir die Frage gestellt.

Ja, hatte es und deswegen hatte ich ja auch "Danke für den Tip" gesagt. 
Das war der Kern des Problems.

Alles andere war nur noch meine Unfähigkeit, den Godbolt zu beherrschen 
und eine vernünftige Herumprobierumgebung zu schaffen.

Es hat ja am Schluss geklappt, und

Nico W. schrieb:
> Wo ist denn das Problem das Millis aus meinem Beispiel zu
> übernehmen?

ja, das hätte ich mal tun sollen. Und Eric B. und A. K. haben auch gute 
Vorschläge. Und schön, dass Axel S. mir wieder ein paar Dinge 
wachgerufen hat.

Das einzige Problem ist, der zu oft unterschwellig unfreundliche und 
leicht überhebliche Ton. In keinem anderen Forum der Welt nehmen sich 
die Mitglieder diesen "Gotteston", Tenor "Du kleiner Wurm, freu Dich, 
dass ich Dich nicht zerquetsche" heraus.

Man wird wie ein Idiot behandelt und es spielt auch keine Rolle, dass 
ich in meinem Leben >1Mio Zeilen C-Code geschrieben habe. Mir bleibt 
also nur noch, wie so vielen anderen hier, mich irgendwann wieder als 
Gast mit neuer Identität anzumelden. Nette Leute gibts hier auch, aber 
sie sind so selten

von Stefan F. (Gast)


Lesenswert?

DerAltePete schrieb:
> Das einzige Problem ist, der zu oft unterschwellig
> unfreundliche und leicht überhebliche Ton.

Du bist aber auch nicht viel besser. Hast damit angefangen, Fehler im 
Compiler herauf zu beschwören. Dabei wissen wir alle, dass der Fehler in 
99% der Fälle vor dem Bildschirm sitzt.

> In keinem anderen Forum der Welt nehmen sich die Mitglieder
> diesen [ton] ... heraus.

Doch. Nicht überall aber in vielen Foren. Zum Beispiel im Heise Forum, 
oft auch auf Tagesschau.de und in diversen Beauty Foren die meine Frau 
nutzt geht es auch heftig ab.

von DerAltePete (Gast)


Lesenswert?

Stefanus F. schrieb:
>> In keinem anderen Forum der Welt nehmen sich die Mitglieder
>> diesen [ton] ... heraus.
>
> Doch. Nicht überall aber in vielen Foren. Zum Beispiel im Heise Forum,
> oft auch auf Tagesschau.de und in diversen Beauty Foren die meine Frau
> nutzt geht es auch heftig ab.

Na dann ist ja alles im Lot.

Adieu

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.