C-> Rückgabewerte?!

Gast #6069904
Lesenswert?

Halli Hallo (:

Was genau bewirkt die Abfrage in der "return" Anweisung?
Was wird denn im Endeffekt zurückgegeben?
1
uint8_t PICC_IsNewCardPresent() 
2
{
3
  byte bufferATQA[2];
4
  byte bufferSize = sizeof(bufferATQA);
5

6
  // Reset ModWidthReg
7
  RFIDWrite(ModWidthReg, 0x26 );
8

9
  StatusCode result = PICC_RequestA( bufferATQA, &bufferSize );
10
  return (result == STATUS_OK || result == STATUS_COLLISION);
11
}
#6069922
Lesenswert?

Der Ausdruck wertet zu bool aus, dann wird er aber implizit in ein 
uint8_t gecastet weil die Funktion so deklariert ist. Letzteres finde 
ich unschön, der Rückgabewert einer Funktion sollte als das deklariert 
sein was er eigentlich ist, in diesem Falle bool.

Viele C-Programmierer haben damit kein Problem weil sie diese 
Schlampigkeit schon immer so gewohnt waren, ich jedoch der mit Pascal 
aufgewachsen ist habe dazu jedoch eine wesentlich strengere Einstellung 
und ich bin der festen Überzeugung daß es hilfreich ist möglichst 
penibel auf die Wahl seiner seiner Datentypen zu achten, schon allein 
der Lesbarkeit und Dokumentation zuliebe, selbst wenn der Compiler es 
ignoriert.
(Firma: www.elpra.de) Persönliche Seite #6069929
Lesenswert?

Bernd K. schrieb:
> Letzteres finde
> ich unschön, der Rückgabewert einer Funktion sollte als das deklariert
> sein was er eigentlich ist, in diesem Falle bool.

Tut es doch. Der == Operator liefert wie Sebastian bereits schrieb 0 
oder 1 als Integer. C kennt nativ erstmal keinen Boolean Typ, siehe 
auch:

https://stackoverflow.com/questions/1921539/using-boolean-values-in-c
#6069944
Lesenswert?

Man könnte / sollte das als C++ ansehen:

Jenny A. schrieb:
> uint8_t PICC_IsNewCardPresent()
> {
>   byte bufferATQA[2];
>   byte bufferSize = sizeof(bufferATQA);
>
>   // Reset ModWidthReg
>   RFIDWrite(ModWidthReg, 0x26 );
>
>   StatusCode result = PICC_RequestA( bufferATQA, &bufferSize );
>   return (result == STATUS_OK || result == STATUS_COLLISION);
> }

Denn die Deklaration
1
uint8_t PICC_IsNewCardPresent();

hieße ja in C eine Funktion mit beliebiger Parameterliste, und in C++ 
eine Funktion mit leerer Parameterliste.
Es sei denn, es ist C2x-Code.
Moderator Persönliche Seite #6069980
Lesenswert?

Wilhelm M. schrieb:
> Bzw. vielen ist das einfach gar nicht bewusst,

Vielen sind auch die möglichen Compiler-Switches nicht bewusst. Ein

   -Wstrict-prototypes

hätte den Fehler direkt aufgedeckt.

Generell empfiehlt sich immer, mindestens die Optionen

    -Wall -Wextra -Wstrict-prototypes -Werror

anzuwenden. Sicher gibt es da noch ein paar mehr. Aber nicht alle 
Optionen zu Warnungen sind immer sinnvoll.
Moderator #6069989
Lesenswert?

Stefan F. schrieb:
> Das "void" bei leeren Parameterlisten ist schon laaaaange optional.

Wenn man es aber weglässt, wird daraus eine K&R-Deklaration, d.h. Anzahl
und Typ der Parameter sind unbestimmt. Beispiel:

1
void func1();
2
void func2(void);
3

4
main(void) {
5
  func1(1, 2, 3); // in C18 korrekt (keine Typprüfung), in C2x und C++ Fehler
6
  func2(1, 2, 3); // Fehler
7
}
Moderator Persönliche Seite #6069992
Lesenswert?

Stefan F. schrieb:
> Das "void" bei leeren Parameterlisten ist schon laaaaange optional. Ich
> kann mich gar nicht mehr daran erinnern, es jemals hingeschrieben zu
> haben.

Bei C++ ist das "void" tatsächlich optional.

Aber Vorsicht:

Bei C bedeutet eine Deklaration einer Funktion mit leerer 
Parameterliste: "Ich weiß nicht, ob die Funktion Parameter benötigt oder 
nicht."

So kann man schreiben:
action.c:
1
int action (char * str)
2
{
3
    printf ("%s\n", str);
4
    return 0;
5
}

action.h:
1
int action ();

Und dann in main.c:
1
#include "action.h"
2
...
3
    action ();

Das geht anstandslos durch den C-Compiler, wenn man es nicht explizit 
verbietet (z.B. beim gcc mit -Wstrict-prototypes).

Folge: Das Programm wird compiliert, crasht dann aber beim Aufruf.

Grund: Vor ANSI-C kannte C überhaupt keine Prototypes. Da wurden 
Funktionen immer mit leeren Parameterlisten deklariert - egal ob sie 
welche benutzten oder nicht.

Ich sehe das alt Altlast, die in diesem Jahrtausend besser über Bord 
gekippt werden sollte.
#6069999
Lesenswert?

Tobias B. schrieb:
> Tut es doch. Der == Operator liefert wie Sebastian bereits schrieb 0
> oder 1 als Integer

Das ist es doch was ich meinte, auch wenn es für den Compiler das selbe 
ist wie ein int oder aus irgendwelchen Legacy-Gründen ein int geliefert 
wird obwohl eigentlich von der Intention her ein bool gemeint und 
gewollt ist kann man doch auch bool hinschreiben um dem Leser klar zu 
machen daß diese Funktion tatsächlich nur wahr oder falsch liefert und 
eben keine beliebige Integerzahl. Das sind subtile Feinheiten (es gibt 
noch mehr davon in vielen Bereichen) die in Summe den ganzen Code 
angenehmer zu lesen machen.
#6070005
Lesenswert?

Bernd K. schrieb:
> Das ist es doch was ich meinte, auch wenn es für den Compiler das selbe
> ist wie ein int oder aus irgendwelchen Legacy-Gründen ein int geliefert
> wird obwohl eigentlich von der Intention her ein bool gemeint und
> gewollt ist kann man doch auch bool hinschreiben um dem Leser klar zu
> machen daß diese Funktion tatsächlich nur wahr oder falsch liefert und
> eben keine beliebige Integerzahl.

Genau! -> "Stop using C" [Kate Gregory] Und wer diesen Vortrag gehört 
hat, versteht vllt jetzt, was er sagen will. Man könnte auch für den 
Title "Stop using the C-habit in C++ or C" wählen.
#6070036
Lesenswert?

Yalu X. schrieb:
> Auch C2x ist C bzw. wird es sein. Dort sollen die K&R-Parameterlisten
> abgeschafft werden, so dass dann
>
> void func() {
>
> gleichbedeutend ist mit
>
> void func(void) {
>
> Darauf wollte Wilhelm wohl hinaus.

Genau!
Meistens schreibe ich zwar C++ oder C++17/C++2a, aber hier meinte ich
tatsächlich C2x, also den kommenden C-Standard, in dem dann foo(void) 
äquivalent zu foo() wird.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren