Zwecks UART-Empfang ohne Interrupt muss man ja nur das RX Ready Flag lesen und dann das RX Datenregister. Ich will nur wissen, /ob/ etwas ankommt, die Daten selbst sind uninteressant. Das Datenregister muss ich aber trotzdem lesen, damit das Flag gelöscht wird. Wie schreibt man das in C am schönsten?
1
intdummy=uart->RDR;
gibt eine Warnung, weil dummy nicht weiter benutzt wird. Statt dummy irgendeine andere Variable nehmen, die an der Stelle zufällig nicht gebraucht wird? Das geht ja wohl garnicht.
1
(void)uart->RDR;
funktioniert angeblich, aber ist das offiziell? Funktioniert das auch mit anderer Optimierung oder einem anderen Compiler?
funktioniert angeblich, aber ist das offiziell? Funktioniert das auch
mit anderer Optimierung oder einem anderen Compiler?
Ja. Die Evaluierung eines volatile-Werts darf nicht wegoptimiert werden, selbst wenn der Wert nicht benutzt wird. Das (void) deaktiviert lediglich die Warnung. Das ist zwar nicht garantiert, hat aber keinen negativen Effekt, und es ist kein Beinbruch falls bei irgendeinem Compiler doch eine Warnung kommt.
okay, zu löschen geht das Flag alleine beim ATmega nicht. Wäre dennoch schön gewesen wenn man wüßte um welchen Controller es sich überhaupt handelt. Wird ja derzeit nur angenommen.
Dass sich ein anderer Compiler anders verhält, ist doch klar. Bei manchen Dingen darf er das, bei anderen muss er sich an den Standard halten. Die entscheidende Frage ist doch: muss er das Hardware-Register auf jeden Fall lesen? Als Bonusfrage noch: wie schreibt man das so, dass es keine Warnung gibt?
Die Evaluierung eines volatile-Werts darf nicht wegoptimiert werden,
selbst wenn der Wert nicht benutzt wird. Das (void) deaktiviert
lediglich die Warnung.
Ich finde, das (void) beschreibt auch gut, was da passiert.
es ist kein Beinbruch falls bei irgendeinem
Compiler doch eine Warnung kommt.
Naja, ein braves Programm sollte keine Warnungen ausspucken, auch, wenn alle eingeschaltet sind.
Wäre dennoch schön gewesen wenn man wüßte um welchen Controller
es sich überhaupt handelt.
z.B. STM32F205RET6, STM32L031C4T6, STM32L412KBT6, R5F565N7ADFP... Eigentlich sollte es eine reine C-Frage sein. Natürlich darf man das Flag auch direkt löschen, die Frage ist, was findet ihr verständlicher?
Ich finde, das (void) beschreibt auch gut, was da passiert.
So ist es. Ein Typecast nach void wird auch an anderen Stellen benutzt um (nicht nur dem Compiler, sondern auch dem geneigten Leser) explizit mitzuteilen: "Da gibt es einen Wert, aber der wird weggeschmissen."
Insofern wäre ein Compiler auch schlecht beraten, für genau diesen Fall trotzdem noch eine Warnung zu generieren.
So ist es. Ein Typecast nach void wird auch an anderen Stellen benutzt
um (nicht nur dem Compiler, sondern auch dem geneigten Leser) explizit
mitzuteilen: "Da gibt es einen Wert, aber der wird weggeschmissen."
ACK.
Insofern wäre ein Compiler auch schlecht beraten, für genau diesen Fall
trotzdem noch eine Warnung zu generieren.
Ich kenne keinen. Ganz im Gegenteil: Durch das (void) davor kann man oft die Warnung verhindern. Die StdPeripheral-Lib für die STM32 hat zum Beispiel an einigen Stellen die Macke, dass sie einen Funktionsparameter zwar in der Parameter-Liste aufführen, diesen dann aber gar nicht in der Funktion selbst nutzen. Bei eingeschalteten Warnungen (-Wextra) meckert der Compiler (gcc) dann: "error: unused parameter ‘param3’ [-Werror=unused-parameter]"
Abhilfe schafft dann ein einfaches:
1
(void)param3;
direkt als erstes Statement innerhalb der Funktion.
Ohne das (void) davor erhält man übrigens dann die Warnung: "warning: statement with no effect [-Wunused-value]"
Wäre dennoch schön gewesen wenn man wüßte um welchen Controller
es sich überhaupt handelt.
z.B. STM32F205RET6, STM32L031C4T6, STM32L412KBT6, R5F565N7ADFP...
Eigentlich sollte es eine reine C-Frage sein. Natürlich darf man das
Flag auch direkt löschen, die Frage ist, was findet ihr verständlicher?
Wenn man das Flag bei den STM selbst löschen kann, dann bleibt das eine reine Geschmacksfrage. Kommentieren sollte man die Zeile sowieso warum man das macht. Ich würde das Flag direkt löschen, weil das bestimmt auch schneller ist.
Vielleicht schaffen sie's ja noch bis zum 31. 12. ;-)
Danke für die Bestätigung, hatte das nur kurz beim Überfliegen einer der Mails gesehen. Habe nicht die rechte Zeit, mir die kompletten (teils recht länglichen) Diskussionen immer anzusehen.
Vielleicht auch das :), wie ich schon schrieb, ich habe da lange nicht mehr rein geschaut. Ich hatte mir nur gemerkt, dass es überhaupt ein Attribut dafür gibt.
Das hat natürlich dann den Vorteil (auch gegenüber dem unbenannten Parameter), dass man sowas machen kann:
Das sind die optimalen Einstellungen für das LCD. Im Ernst, die sind echt, also ausprobiert und dann hier als Default eingetragen. Am besten ist cf_note, die Tonhöhe trifft genau die Resonanz vom Beeper :)
Ich kriege nur eine Warnung, wenn ich mit dem gelesenen Wert etwas berechne und nicht verwende. Der reine Lesezugriff bleibt ohne Warnung. Da ist wohl der AVR-GCC etwas intelligenter bzw. weniger besserwisserisch.
1
main.c:7:7: warning: value computed is not used [-Wunused-value]
Da ist wohl der AVR-GCC etwas intelligenter bzw. weniger
besserwisserisch.
Hat wohl eher damit zu tun, dass UDR0 als volatile deklariert ist. Das Lesen eines volatile-Registers ohne Zuweisung ist auf jeden Fall sinnvoller als das Lesen einer Variablen ohne anschließende Zuweisung. Mach das mal mit einer Variablen, dann wirst Du auch beim AVR-gcc die Warnung (Voraussetzung: -Wextra) sehen.
In C++ wurde das auch bereits mit C++17 eingeführt.
Wobei C++ kürzere Release-Zyklen für den Standard hat, was wohl wiederum an der IEEE-Policy liegt. Ohne ein konkretes Projekt müsste sich die working group ansonsten zwischendrin auflösen.
Hat wohl eher damit zu tun, dass UDR0 als volatile deklariert ist. Das
Lesen eines volatile-Registers ohne Zuweisung ist auf jeden Fall
sinnvoller als das Lesen einer Variablen ohne anschließende Zuweisung.
Mach das mal mit einer Variablen, dann wirst Du auch beim AVR-gcc die
Warnung (Voraussetzung: -Wextra) sehen.
Die Option -Wall beinhaltet auch -Wunused-value. Damit bekommt man eine Warnung, wenn man einen Ausdruck hat, dessen Ergebnis nicht verwendet wird (siehe: UDR + 1), was ein rvalue ist.
In UDR steckt ja der Indirektionsoperator / Zeigerdereferenzierungsoperator (*) drin, das Ergebnis ist ein volatile-lvalue. Wegen der volatile-Qualifizierung ist dem Compiler klar, dass hier nicht nur ein Wert bestimmt werden soll, sondern dass auch ein Seiteneffekt erzeugt werden soll. volatile bedeutet ja, dass es sich um eine "besondere Speicherzelle" handelt, für die die üblichen Annahmen, die Optimierungen ermöglichen, nicht gelten. Daher keine Warnung.
Ich kann mir auch nicht vorstellen, dass ein gcc für einen STM32 dümmer
ist als für einen AVR, s.a.
Ist es auch nicht, da es eine Frontend-Warnung ist, und das ist für gcc und avr-gcc natürlich identisch.
Korrekt, danke für die Richtigstellung. Aber -Wall enthält unverständlicherweise nicht -Wunused-parameter, auf welches sich mein Beispiel für STM32 bezog. Hier benötigt man -Wextra.
1
$ cat a.c
2
#include <stdio.h>
3
4
void
5
foo (int x, int y)
6
{
7
x;
8
}
9
10
int
11
main ()
12
{
13
foo (3, 4);
14
return 0;
15
}
16
17
$ cc -O -Wall a.c
18
a.c: In function ‘foo’:
19
a.c:6:5: warning: statement with no effect [-Wunused-value]
20
x;
21
^
22
23
$ cc -O -Wall -Wextra a.c
24
a.c: In function ‘foo’:
25
a.c:6:5: warning: statement with no effect [-Wunused-value]