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 statt unsigned int auch einfach unsigned schreiben, das dürften sogar die meisten so machen. Das int kann man genauso bei short 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?


  • Mod

    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 , nicht gpio_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.


  • Mod

    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 🙂


  • Mod

    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ür foo ? 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.


  • Mod

    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...


  • Mod

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


  • Mod

    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.


Anmelden zum Antworten