Guten Morgen,
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?
Bauform B. schrieb:> 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.
Peter D. schrieb:> UDR0; UDR0; UDR0;
Ohne das (void) kommt aber wieder die Warnung.
Hallo,
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.
Niklas G. schrieb:> Ohne das (void) kommt aber wieder die Warnung.
Welche Warnung, ich bekomme keine.
Kannst Du mal deren kompletten Text posten (C&P) und die Codezeile dazu.
Und das Target nennen.
Peter D. schrieb:> Niklas G. schrieb:>> Ohne das (void) kommt aber wieder die Warnung.>> Welche Warnung, ich bekomme keine.
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?
Und die Antwort darauf sieht so aus:
Niklas G. schrieb:> 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.
Veit D. schrieb:> 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?
Bauform B. schrieb:> 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.
Jörg W. schrieb:> 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]"
Bauform B. schrieb:> Veit D. schrieb:>> 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.
Frank M. schrieb:> Jörg W. schrieb:>> Ab C23> Sehr schick! Und auch sinnvoll.
Am 1. April gab's den letzten Draft, da steht es drin, zwar in Klammern
und mit nur zwei Worten im Nebensatz, aber immerhin.
1
6.9.1 Function definitions
2
3
7 The declarator in a function definition specifies the name of the
4
function being defined and the types (and optionally the names)
5
of all the parameters;
6
7
9 Each parameter has automatic storage duration; its identifier,
8
if any, is an lvalue.
Aber es wird wohl ein C24 draus...
1
Revised C23 Schedule WG 14 N 2984
2
3
Start Event Days Completed
4
2023-02-13 Editor readies document for DIS 7 2023-02-20
5
2023-02-20 ISO editing (submit DIS ballot) 56 2023-04-17
Bauform B. schrieb:> Aber es wird wohl ein C24 draus...
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.
Wilhelm M. schrieb:> Einfach C++ benutzen ;-) Da geht das!
Wundert nun nicht so sehr, beide Standards versuchen ja schon, möglichst
viel synchron zu halten.
Jörg W. schrieb:> int foo(int something, char /* no name here */) {> // ...> }Jörg W. schrieb:> Wilhelm M. schrieb:>> Einfach C++ benutzen ;-) Da geht das!>> Wundert nun nicht so sehr, beide Standards versuchen ja schon, möglichst> viel synchron zu halten.
War mir gar nicht bewusst, daß C das nicht kennt. gcc compiliert das ab
gcc 11, lustigerweise sogar mit -std=c90.
Oliver
Veit D. schrieb:> sollte das für C und C++ nicht eher>> maybe unused>> sein?
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 :)
Niklas G. schrieb:> Ohne das (void) kommt aber wieder die Warnung.
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]
Peter D. schrieb:> Der reine Lesezugriff bleibt ohne Warnung.
-Wextra eingeschaltet?
> 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.
Ich kann mir auch nicht vorstellen, dass ein gcc für einen STM32 dümmer
ist als für einen AVR, s.a.
Beitrag "Re: [c] wie wirft man UART-Daten weg?"
Rolf M. schrieb:> 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.
Frank M. schrieb:> 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.
Rolf M. schrieb:> Veit D. schrieb:>> Hallo,>>>> sollte das für C und C++ nicht ehermaybe unused>> sein?>> Ja. In C++ wurde das auch bereits mit C++17 eingeführt.
Und das schöne daran ist, dass man es nicht nur für (Parameter-)
Variablen benutzen kann, sondern für bspw. structured-bindings und
Typ-Aliase.
Wilhelm M. schrieb:> Die Option -Wall beinhaltet auch -Wunused-value.
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]