kuriose Variablendeklaration
-
ich bin eben über folgendes Konstruktu gestolpert aber irgendwie ergibt sich mir der Sinn dahinter nicht ganz, scheint aber so als ob es ohne Zicken compiliert!
const struct gpio_desc *desc = dev_get_drvdata(dev); unsigned gpio = desc - gpio_desc;
stammt aus dem Exynos GPIO driver
in meinen Augen fehlt da zwischen unsigned und gpio was oder ich hab ne Bildungslücke und da wird was aus dem Struct davor impliziert!?
Vielen Dank schonmal
-
Ceos schrieb:
in meinen Augen fehlt da zwischen unsigned und gpio was
Was soll da fehlen,
int
? Man kann stattunsigned int
auch einfachunsigned
schreiben, das dürften sogar die meisten so machen. Dasint
kann man genauso beishort int
,long int
,signed int
etc. weglassen.
-
ganz ehrlich, war mir SO absolut unbekannt!
okay jetzt wo du short, long usw. ins Feld führst wird mir das erst wirklich bewusst dass ich es dort auch immer weglasse! Nur ohne jegliche notation kannte ich das noch nicht
-
Dieser Thread wurde von Moderator/in nman aus dem Forum Linux/Unix in das Forum C (C89, C99 und C11) verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Was ich nicht verstehe:
desc ist ein Zeiger, so weit, so gut. Aber gpio_desc ist der Name einer Struktur, wie kann ich den von einem Zeiger subtrahieren?
-
Belli schrieb:
Aber gpio_desc ist der Name einer Struktur, wie kann ich den von einem Zeiger subtrahieren?
Es kann ja durchaus noch eine Variable gpio_desc im gleichen Scope geben.
Im übrigen ist der Name der Struktur immer noch
struct gpio_desc
, nichtgpio_desc
wie in C++. Aber selbst wenn, dann ginge das ja trotzdem:struct foo { }; foo foo; // Absolut in Ordnung in C++
Geht nicht mehr bei einem typedef.
(Das heißt nicht, dass du nicht Recht hast und der Code einfach Unsinn ist. Ich gehe sogar davon aus. Wollte bloß darauf aufmerksam machen, dass es möglich ist.)
-
SeppJ schrieb:
struct foo { }; foo foo; // Absolut in Ordnung in C++
Geht nicht mehr bei einem typedef.
Hab ich nicht gewusst ...
-
SeppJ schrieb:
(Das heißt nicht, dass du nicht Recht hast und der Code einfach Unsinn ist. Ich gehe sogar davon aus.
Wieso das denn? Da spricht doch überhaupt nichts für, im Gegenteil.
-
Bashar schrieb:
Wieso das denn? Da spricht doch überhaupt nichts für, im Gegenteil.
Weil ich die Namensgebung, wie Belli, doch etwas kurios finde, auch wenn sie technisch möglich ist. Ich würde daher einen Tippfehler erwarten.
-
der OP schrieb:
stammt aus dem Exynos GPIO driver
Man sieht aber auch ohne diese Information, dass das kein Wegwerfbeispiel mit Tippfehler sein kann.
-
ich muss gestehen dass die 2 Zeilen vll. auch ein klein wenig aus dem Zusammenhang gerissen wurden und ich mir nicht mal sicher bin ob es sich um reines C oder doch C++ handelt. Aber da ich im Moment eher am Kontext interssiert bin und dieser kleine Stolperstein mir gestern eine Stunde lang den Nerv geraubt hat dachte ich man fragt lieber einmal die Spezialisten als dumm zu sterben.
static ssize_t gpio_value_show(struct device *dev, struct device_attribute *attr, char *buf) { const struct gpio_desc *desc = dev_get_drvdata(dev); unsigned gpio = desc - gpio_desc; ssize_t status; mutex_lock(&sysfs_lock); if (!test_bit(FLAG_EXPORT, &desc->flags)) { status = -EIO; } else { int value; value = !!gpio_get_value_cansleep(gpio); //<--- an der Stelle würde ich behaupten es ist C++ // "!!" in der kombi kenn ich nur als "missbrauch" des operator! um ein objekt als negiertes "nicht" zu bool zu konvertieren if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) value = !value; status = sprintf(buf, "%d\n", value); } mutex_unlock(&sysfs_lock); return status; }
DAs ist jetzt nur die Methode der Vollständigkeit halber, für mich ist das Thema soweit erledigt, aber ihr dürft gern ncoh angeregt diskutieren
-
Ich bin mir ziemlich sicher, dass es C ist. Nichts deutet auf C++. Viele Stellen (z.B. den "scoped" Mutex) könnte man mit C++ so viel schöner machen, das muss einen Grund haben, warum das nicht benutzt wird.
Das
!!foo
ist wohl eine trickreiche (und evtl. schnellere) Schreibweise fürfoo ? 1 : 0
. Außerdem eine weitere Stelle, die man in C++ viel schöner mittels bool hätte lösen können.
-
ich habs nicht geschrieben XD
ich würde es wahrscheinlich viel umständlicher machen ... in C fehlt mir ein wenig die Praxis, ich hab sonst immer für Atmel µController mit C programmiert aber sonst mich eher auf .NET oder Java beschränkt ... Anwendungen schreiben sich mit nem guten Framework einfach schneller und aufm µC wirds spätestens bei Interrupts und inline assembler unschön also muss man es nicht elegant machen es muss nur schnell sein.
-
Schnell und elegant schließt sich nicht aus. Das war sogar die Hauptmotivation bei der Erfindung von C++.
Trotzdem ist das reines C und für reines C auch ganz ok. Ich hätte wahrscheinlich ein paar Sachen anders gemacht, aber vielleicht hatte der Autor gute Gründe, die mir nicht bekannt sind.
-
SeppJ schrieb:
Das
!!foo
ist wohl eine trickreiche (und evtl. schnellere) Schreibweise für**foo ? 1 : 0
**kannst du das bitte nochmal kurz erläutern? foo ? 1 : 0
-
Länger ausgeschrieben:
int value; if (foo) value = 1; else value = 0;
Wobei mir ehrlich gesagt der Sinn in diesem Zusammenhang fehlt...
-
Nathan schrieb:
Wobei mir ehrlich gesagt der Sinn in diesem Zusammenhang fehlt...
Es wird ja hinterher ausgegeben. Da interessiert wahrscheinlich nur ob value == 0 war oder nicht. Da möchte man sich nicht sein Log mit dem genauen Wert vollmüllen.
-
Ach so.
Gewissermaßen ein static_cast<bool>?
-
Nathan schrieb:
Ach so.
Gewissermaßen ein static_cast<bool>?Ja.
-
SeppJ schrieb:
Ich bin mir ziemlich sicher, dass es C ist. Nichts deutet auf C++. [...] könnte man mit C++ so viel schöner machen
Was soll das C-Bashing? Ich finde den Code sehr lesbar und übersichtlich.
static ssize_t gpio_value_show(struct device *dev, struct device_attribute *attr, char *buf) { const struct gpio_desc *desc = dev_get_drvdata(dev); unsigned gpio = desc - gpio_desc; ssize_t status; mutex_lock(&sysfs_lock); if (!test_bit(FLAG_EXPORT, &desc->flags)) { status = -EIO; } else { int value; value = !!gpio_get_value_cansleep(gpio); if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) value = !value; status = sprintf(buf, "%d\n", value); } mutex_unlock(&sysfs_lock); return status; }
versus
namespace { class gpio_value_show { public: gpio_value_show(device const& dev, device_attribute const& attr) : dev(dev), attr(attr) { } private: device const& dev; device_attribute const& attr; }; template <typename CharT> std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, gpio_value_show const& gpio_value_show_dummy) { gpio_drvdata const& desc = gpio_value_show_dummy.dev.get_drvdata(); std::lock_guard<type_of_sysfs_lock> yet_another_random_name(sysfs_lock); if (!(desc.get_flags() & FLAG_EXPORT)) { if (os.exceptions() & std::ios_base::failbit) throw invalid_io_exception("FLAG_EXPORT"); else os.setstate(std::ios_base::failbit) } else { std::size_t gpio = desc - gpio_desc; bool value = static_cast<bool>(gpio_get_value_cansleep(gpio)); if (desc.get_flags() & FLAG_ACTIVE_LOW) { value = !value; } // ?: needed because of the boolalpha flag os << (value ? CharT('1') : CharT('0')) << CharT('\n'); } return os; } }
Der C Code ist schnell und es ist klar, was er macht.
Der C++ Code ist (wie jeder C++ Code) überladen mit vermeintlich "höherer Abstraktion". Jedenfalls muss man erst einmal suchen, was da genau passiert. Die Hälfte ist Boilerplate und meistens ist Boilerplate und Code gemischt. Ausserdem bin ich sicher, dass das Binary um ein Vielfaches grösser ist. Und in der Ausführung um ein Vielfaches langsamer.