Warum sowas: (1u << 16) - 1

L I V E Stammtisch ab 20:30 Uhr im Chat
  • Moin!

    Ich habe hier ein Beispielcode in C, da wird (1u << 16) - 1 als Parameter an eine Funktion übergeben.

    Erster Gedanke was soll das denn? Mal auf einem Zettel die Bits geschoben und dann AHA.

    Um sicher zu sein, ein kleines Programm geschrieben. Das kommt zum gleichem Ergebnis.

    C
    #include <stdlib.h>
    #include <stdio.h>
    #include <stdint.h>
    
    int main (void)
    {
      uint32_t zahl = (1u << 16) - 1;
    
      printf("Das ist die Zahl: %d oder %X\n",zahl,zahl);
    } 

    Ergebnis: Das ist die Zahl: 65535 oder FFFF

    Nun die Frage, warum macht ein Programmierer so ein Beispiel in einer Dokumentation für eine SDK?

    Weil, später werden direkt Zahlen übergeben.

    Eventuell kennt ihr ja einen Grund.

    Danke.

    73 de Bernd

    Ich habe KEINE Ahnung und davon GANZ VIEL!!
    Bei einer Lösung freue ich mich über ein ":thumbup:"
    Vielleicht trifft man sich in der RPi-Plauderecke.
    Linux ist zum Lernen da, je mehr man lernt um so besser versteht man es.

  • Ganz klar Punkt vor Strich und somit ist << auch ein Punkt??

    (nein ohne Klammern kommt 8000 Hex rauß)

    *EDIT* Smiley vergessen :) (bin kein Mathe-genie)

    PS:

    Das ist die Zahl: 65535 oder FFFF

    Ich interpretiere es so. Nehme 1 schiebe 16 mal nach links und ziehe 1 ab???

    Gibt es in Assembler nicht einen Befehl um Register nach links zu schieben um sich Multiplikationen zu sparen. Aber vielleicht kommt der Code auch einem Register in Assembler nahe. Sorry Wurzelziehen in Assembler ohne Gleitkomma Rechenwerk ist schon was :)

    4 Mal editiert, zuletzt von det_lev_da (2. September 2021 um 21:54)

  • Ganz klar Punkt vor Strich und somit ist << auch ein Punkt??

    Jetzt hab ich doch tatsächlich meinen alten Kernighan/Ritchie aus dem Regal genommen um zu sehen was Vorrang hat.

    In der Tat, + und - hat Vorrang über << und >>, also MUSS man die Klammern setzen.

    BTW: Kernighan/Ritschie, "Programmieren in C" ist ein Buch der Erfinder/Entwickler von C, und auch wenn sich die Sprache mit den Jahrzehnten extrem weiter entwickelt hat ist es ein absolutes Standardwerk, das jeder C/C++ Programmierer haben sollte, und mindestens einmal durchgearbeitet haben sollte. Die Syntax hat sich nicht verändert.

  • Ich interpretiere es so. Nehme 1 schiebe 16 mal nach links und ziehe 1 ab???

    genau. Mit Klammern.


    ohne Klammern kommt 8000 Hex rauß

    genau, weil - Vorrang vor << hat, also "ziehe 1 von 16 ab und schiebe eine 1 (16-1) mal nach links = 2 hoch 15 = 0x8000

    Aber vielleicht kommt der Code auch einem Register in Assembler nahe.

    Das ist das Geniale an C: die Sprache ist sehr nahe an der Hardware gebaut und dennoch erlaubt sie genug Abstrahierung von der Maschine so dass Menschen damit umgehen koennen. Das heisst, wenn man C programmiert bekommt man sehr effizienten Code. Ein guter Compiler ersetzt in den allermeisten Fällen die Assembler-Programmierung.

  • Ich tippe auf b, c & e und hoffe sehr, dass das von Bernd666 eine multiple Choice Frage war. :D

  • Hallo Leute, was mir "entfallen" war, verschiebt man z.B "3" einmal nach links verdoppelt es sich, ich hab gedacht ^2 als quadratisch. Nein eine Zahl einamal nach links schieben == doppelt also * 2 nicht ^2 :) juhu

    Drehen=rotate!=schieben :) als wenn man die Ausführungszeit optimieren will nicht * 2, sondern 1 mal Drehen :)

  • ... wenn man die Ausführungszeit optimieren will ...

    Dann wird das evtl. der Grund sein, warum der Programmierer das so geschrieben hat.

    "a << b" vs. "a * 2 pow b"

    The most popular websites without IPv6 in Germany.  IPv6-Ausreden

    Meine PIs

    PI4B/8GB (border device) OpenBSD 7.4 (64bit): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server

    PI3B+ FreeBSD 14.0-R-p3 (arm64): SSH-Serv., WireGuard-Serv., ircd-hybrid-Serv., stunnel-Proxy, Mumble-Serv., ddclient

    PI4B/4GB Bullseye-lite (64bit; modifiziert): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server, botamusique, ample

  • wenn man die Ausführungszeit optimieren will

    ... dann hätte ich gleich 0xFFFF geschrieben, weil man ja nicht weiss (also ich zumindest nicht) was der Compiler aus (1u<<16)-1 macht.

    Ein guter Compiler merkt dass er die Rechnung bereits zur Kompilierzeit machen kann und tut das dann auch. Ein weniger guter wird die Schiebeoperation und die Subtraktion in Assember Code übersetzen.

    Würde mich mal interessieren was der gcc Compiler draus macht. Da gibts ne Kommandozeilen Option mit der man den Assembler Code angezeigt bekommt. Ist mir aber grad entfallen welche.

  • Da gibts ne Kommandozeilen Option mit der man den Assembler Code angezeigt bekommt.

    Mit "-S". Lt. manpage von gcc:

    Zitat

    -S Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembler

    code file for each non-assembler input file specified.

    By default, the assembler file name for a source file is made by replacing the suffix .c, .i, etc., with

    .s.

    Input files that don't require compilation are ignored.

    The most popular websites without IPv6 in Germany.  IPv6-Ausreden

    Meine PIs

    PI4B/8GB (border device) OpenBSD 7.4 (64bit): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server

    PI3B+ FreeBSD 14.0-R-p3 (arm64): SSH-Serv., WireGuard-Serv., ircd-hybrid-Serv., stunnel-Proxy, Mumble-Serv., ddclient

    PI4B/4GB Bullseye-lite (64bit; modifiziert): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server, botamusique, ample

  • ... dann hätte ich gleich 0xFFFF geschrieben, weil man ja nicht weiss (also ich zumindest nicht) was der Compiler aus (1u<<16)-1 macht.

    Ein guter Compiler merkt dass er die Rechnung bereits zur Kompilierzeit machen kann und tut das dann auch. Ein weniger guter wird die Schiebeoperation und die Subtraktion in Assember Code übersetzen.

    Würde mich mal interessieren was der gcc Compiler draus macht. Da gibts ne Kommandozeilen Option mit der man den Assembler Code angezeigt bekommt. Ist mir aber grad entfallen welche.

    Ich bin bis jetzt noch nie dazu gekommen einen Mikrocontroller mit C zu programmieren, und ob die heute alle Fließkomma Rechenkern haben.

    Ich hab mal mit einem Elektor-buch mit vielen Beispielen programmiert und der war garantiert nicht für Fließkomma gedacht nein es war 80c535.

    Man kann es schaffen mit solchen Tricks die Geschwindigkeit zu erhöhen. Aber heute bekommt man schon welche für 5 Euro mit Camera :) (ESP??) mit allem drum und dran.

  • Nun die Frage, warum macht ein Programmierer so ein Beispiel in einer Dokumentation für eine SDK?

    Mache ich auch so (mit Python), weil kein Bock habe den Buchstaben F zu zählen und außerdem kann man mit der Methode einfach festlegen, wie viel Bit man haben möchte.

    Python
    def max_val(bits):
        return (1 << bits) - 1

    Pflichtlektüre: 3. Bit Hacks

  • Moin!

    danke für eure rege Teilnahme.

    Ich denke nurazur hat die plausibelste Antwort geschrieben. Es gibt keine Erklärung.

    Mache ich auch so (mit Python), weil kein Bock habe den Buchstaben F zu zählen und außerdem kann man mit der Methode einfach festlegen, wie viel Bit man haben möchte.

    Das kann sein, ist aber hier nicht der Fall.

    Die Funktion wird schon richtig definiert.

    void pio_pwm_set_period(PIO pio, uint sm, uint32_t period)

    Der Aufruf sieht dann so aus.

    pio_pwm_set_period(pio, sm, (1u << 16) - 1);

    Wie es aussieht, erkennt der Compiler die "Rechnung" und setzt die Zahl ein.

    Ich habe den GCC mit meinem Code so aufgerufen.

    gcc -Wall -O0 -S zahl.c

    Und das kommt dabei raus.

    Spoiler anzeigen

    Zum Test habe ich ((1u << 16) - 1) durch 0xffff ersetzt. Die Ergebnisse gleichen sich.

    73 de Bernd

    Ich habe KEINE Ahnung und davon GANZ VIEL!!
    Bei einer Lösung freue ich mich über ein ":thumbup:"
    Vielleicht trifft man sich in der RPi-Plauderecke.
    Linux ist zum Lernen da, je mehr man lernt um so besser versteht man es.

  • Ich denke nurazur hat die plausibelste Antwort geschrieben. Es gibt keine Erklärung.

    Zum Test habe ich ((1u << 16) - 1) durch 0xffff ersetzt. Die Ergebnisse gleichen sich.

    Ich denke, der Programmierer hat das aus Portabilitätsgründen so gemacht-

    (1u << 16) - 1 kann nicht missinterpretiert bzw. nicht missverstanden werden.

    Aber wenn wir es genau wissen wollen, müssten wir den Programmierer fragen.

    The most popular websites without IPv6 in Germany.  IPv6-Ausreden

    Meine PIs

    PI4B/8GB (border device) OpenBSD 7.4 (64bit): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server

    PI3B+ FreeBSD 14.0-R-p3 (arm64): SSH-Serv., WireGuard-Serv., ircd-hybrid-Serv., stunnel-Proxy, Mumble-Serv., ddclient

    PI4B/4GB Bullseye-lite (64bit; modifiziert): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server, botamusique, ample

  • Wie es aussieht, erkennt der Compiler die "Rechnung" und setzt die Zahl ein.

    Passiert bei Python auch, ist aber nicht immer leicht vorherzusagen. Oftmals hat der Compiler zu wenig Informationen für eine Optimierung.

    Ich denke, der Programmierer hat das aus Portabilitätsgründen so gemacht-

    (1u << 16) - 1 kann nicht missinterpretiert bzw. nicht missverstanden werden.

    Wie sehr das missverstanden oder nicht verstanden wird, sehen wir doch hier in diesem Beitrag.

    Keiner hätte wegen 0xFFFF gefragt.

  • Ich denke, der Programmierer hat das aus Portabilitätsgründen so gemacht-

    Ich glaube auf einer 8 Bit CPU kommt was anderes raus und es ist somit nicht portabel :shy: Ich weiss jetzt nicht ob ein Compiler bei einer 8 Bit CPU bei 0xffff meckern wuerde. Erwarten wuerde ich es jedenfalls.

  • Moin framp,

    die C-SDK ist für den Raspberry Pi Pico geschrieben worden. Das /der? SoC RP2040 wird von verschiedenen Herstellern verbaut.

    Arduino, Adafruit, Pimoroni usw.

    73 de Bernd

    Ich habe KEINE Ahnung und davon GANZ VIEL!!
    Bei einer Lösung freue ich mich über ein ":thumbup:"
    Vielleicht trifft man sich in der RPi-Plauderecke.
    Linux ist zum Lernen da, je mehr man lernt um so besser versteht man es.

  • Moin framp,

    Ich glaube auf einer 8 Bit CPU kommt was anderes raus und es ist somit nicht portabel :shy: Ich weiss jetzt nicht ob ein Compiler bei einer 8 Bit CPU bei 0xffff meckern wuerde. Erwarten wuerde ich es jedenfalls.

    Deine Aussage ist richtig, aber, wie geschrieben, ist das eine spezielle SDK für eine bestimmte CPU.

    Nur das wollte ich aussagen...

    73 de Bernd

    Ich habe KEINE Ahnung und davon GANZ VIEL!!
    Bei einer Lösung freue ich mich über ein ":thumbup:"
    Vielleicht trifft man sich in der RPi-Plauderecke.
    Linux ist zum Lernen da, je mehr man lernt um so besser versteht man es.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!