Forum: Compiler & IDEs [c] wie wirft man UART-Daten weg?


von Bauform B. (bauformb)


Lesenswert?

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
int dummy = 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?

von Peter D. (peda)


Lesenswert?

1
UDR0; UDR0; UDR0;
Dann sind alle 3 Puffer leer.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

warum löschst du nicht das Flag?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Veit D. (devil-elec)


Lesenswert?

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.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

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.

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Welche Warnung, ich bekomme keine

Hab keine AVR Toolchain zur Hand.

von Bauform B. (bauformb)


Lesenswert?

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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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]"

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Abhilfe schafft dann ein einfaches:

Ab C23 dann ein
1
  int param3 [[unused]]

;-)

Wenn ich mich recht entsinne (habe lange keine Drafts mehr gelesen), 
müsste dann auch sowas gehen:
1
int foo(int something, char /* no name here */) {
2
  // ...
3
}

von Veit D. (devil-elec)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Ab C23

Sehr schick! Und auch sinnvoll.

von Bauform B. (bauformb)


Lesenswert?

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
6
2023-04-17 DIS ballot                       182  2023-10-16
7
2023-10-16 Contingency                       14  2023-10-30
8
2023-10-30 Editor prepares IS                14  2023-11-13
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Wilhelm M. (wimalopaan)


Lesenswert?

Jörg W. schrieb:
> Wenn ich mich recht entsinne (habe lange keine Drafts mehr gelesen),
> müsste dann auch sowas gehen:
>
>
1
> int foo(int something, char /* no name here */) {
2
>   // ...
3
> }
4
>

Einfach C++ benutzen ;-) Da geht das!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Oliver S. (oliverso)


Lesenswert?

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

von Veit D. (devil-elec)


Lesenswert?

Hallo,

sollte das für C und C++ nicht eher
1
[[maybe_unused]]
sein?

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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:
1
int foo(int something, int debugchannel [[maybe_unused]]) {
2
#ifdef DEBUG
3
  fprintf(debugchannel, "Entering foo(%d) ...\n", something);
4
#endif
5
  // blablah
6
  return 42;
7
}

Ohne das "maybe" könnte der Compiler sich ja beschweren, dass es bei 
DEBUG dann doch benutzt wird.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

immer wieder 42.  :-)  :-)

von Bauform B. (bauformb)


Lesenswert?

Veit D. schrieb:
> immer wieder 42.  :-)  :-)
1
uint16_t  config[cf_cf_size] = {
2
   [ cf_contrast   ] = 42,   // %
3
   [ cf_brightness ] = 17,   // %
4
   [ cf_timeout    ] = 42,   // * 10s
5
   [ cf_volume     ] = 42,   // %
6
   [ cf_note       ] = 42,
7
   [ cf_len        ] = 17,   // * 10ms
8
   [ cf_baud       ] = 4800,
9
};
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 :)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

42 Baud wären aber auch lustig gewesen. ;-)

von Peter D. (peda)


Lesenswert?

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]
2
   UDR0+1;

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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?"

: Bearbeitet durch Moderator
von Rolf M. (rmagnus)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Wilhelm M. (wimalopaan)


Lesenswert?

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.

von Wilhelm M. (wimalopaan)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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]
26
     x;
27
     ^
28
a.c:4:17: warning: unused parameter ‘y’ [-Wunused-parameter]
29
 foo (int x, int y)

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.