Ein "long" als String ?



  • @Mathuas sagte in Ein "long" als String ?:

    long l="Hello World !";
    printf("%s\n",l);  // --> Hello World !
    

    Wie ist so etwas überhaupt möglich ?
    Ich dachte immer, ein "long" sei ein Integer Typ und kann nur Ganzzahlen aufnehmen.
    Wieso gehen auch Strings ?

    Ich bin Danke der Intrinsic.h von den XToolkits darauf gestossen.

        XtSetArg(wargs[i], XtNheight, 25); i++;
        XtSetArg(wargs[i], XtNlabel, "Hallo"); i++;
    
    #define XtSetArg(arg, n, d) \
        ((void)( (arg).name = (n), (arg).value = (XtArgVal)(d) ))
    
    typedef long		XtArgVal;
    

    Noch der Link zu "long": https://de.wikipedia.org/wiki/Datentypen_in_C

    Du scheinst eine ältere Version der libXt zu nutzen.
    Denn in der neusten version ist ein XtArgVal wie folgt definiert (https://github.com/freedesktop/xorg-libXt/blob/master/include/X11/Intrinsic.h)

    typedef XtIntPtr	XtArgVal;
    

    Und XtIntPtr ist wie folgt definiert:

    #if __STDC_VERSION__ >= 199901L
    #include <stdint.h>
    typedef intptr_t	XtIntPtr;
    typedef uintptr_t	XtUIntPtr;
    #else
    typedef long		XtIntPtr;
    typedef unsigned long	XtUIntPtr;
    #endif
    

    das XtArgVal = long gilt nur wenn der compiler __STDC_VERSION__ < 199901 definiert (aka kein C99 oder neuer standard unterstützt bzw. aktiv ist.)



  • @Mathuas sagte in Ein "long" als String ?:

    Ich dachte immer, ein "long" sei ein Integer Typ und kann nur Ganzzahlen aufnehmen.

    chars sind auch nur Ganzzahlen, den den Code für das jeweilige Zeichen speichern. D.h. man kann ein long auch als Abfolge von chars im Speicher interpretieren, was hier getan wird. Das ganze ist natürlich alles andere als sauber und sollte so tunlichst nicht gemacht werden.


  • Mod

    @john-0 sagte in Ein "long" als String ?:

    @Mathuas sagte in Ein "long" als String ?:

    Ich dachte immer, ein "long" sei ein Integer Typ und kann nur Ganzzahlen aufnehmen.

    chars sind auch nur Ganzzahlen, den den Code für das jeweilige Zeichen speichern. D.h. man kann ein long auch als Abfolge von chars im Speicher interpretieren, was hier getan wird. Das ganze ist natürlich alles andere als sauber und sollte so tunlichst nicht gemacht werden.

    Das ist nicht, was hier passiert. Was hier passiert, wurde in der ersten Antwort schon korrekt erklärt. Was du beschreibst wäre so etwas wie hier:

    #include <stdio.h>
    
    int main(void) {
    	const char* str = "Hello World!";
    	long int value = *(long int*) str;
    	printf("%ld %.*s", value, sizeof(value), &value);
    }
    

    Was ein anderes Ergebnis hat (je nach sizeof(value)) und ganz gewiss niemand so programmieren wird, weil man solche Casts weder versehentlich noch absichtlich macht.



  • Danke für die Infos, ich dachte doch fast, mit dem 32Bit Integer sei etwas faul.

    @firefly sagte in Ein "long" als String ?:

    Du scheinst eine ältere Version der libXt zu nutzen.
    Denn in der neusten version ist ein XtArgVal wie folgt definiert (https://github.com/freedesktop/xorg-libXt/blob/master/include/X11/Intrinsic.h)

    Anscheinend wird bei Linux Mint eine veraltet lib der XToolkits mit geliefert. Ich vermute bei Debian und Ubuntu wird dies nicht anders sein.
    Dies verwundert mich, das dies ein grösserer Bug ist. Ein 32Bit Pointer auf einem 64Bit OS.
    Einziger Grund könnte sein, das kaum einer mehr die XToolkit braucht.

    Ich habe jetzt die XToolkits von github genommen und da steht jetzt auch intptr_t.


  • Mod

    @Mathuas sagte in Ein "long" als String ?:

    Dies verwundert mich, das dies ein grösserer Bug ist. Ein 32Bit Pointer auf einem 64Bit OS.

    Ich sehe da nix mit 32 Bit. long ist bei üblichen Linuxcompilern 64 Bit, deswegen klappt das hier ja auch.



  • @SeppJ sagte in Ein "long" als String ?:

    Das ist nicht, was hier passiert. Was hier passiert, wurde in der ersten Antwort schon korrekt erklärt. Was du beschreibst wäre so etwas wie hier:

    Mir war eher folgendes Beispiel im Kopf

    #include <stdio.h>
    
    int main(void) {
        long l = 'H' + 'e' * 256 + 'l' * 256 * 256 + 'l' * 256 * 256 * 256 + (long)'o' * 256 * 256 * 256 * 256 + (long)'!' * 256 * 256 * 256 * 256* 256;
    
        printf("%s\n", &l);
    }
    

    Früher haben das C Compiler oftmals ohne jede Warnung geschluckt.


  • Mod

    Das ist gar nicht mal sooo lange her, dass Compiler da überhaupt warnen. Vermutlich weniger als 10 Jahre. Braucht man schließlich tiefergehende Inspektion des Formatstringinhalts für, anstatt nur eine Analyse der syntaktischen Elemente. Es ist ja prinzipiell auch erst einmal korrektes C; das ist ein völlig legitimer Funktionsaufruf, der nur mit Wissen über die spezielle Semantik von printf als UD erkennbar ist.



  • Ich sehe da nix mit 32 Bit. long ist bei üblichen Linuxcompilern 64 Bit, deswegen klappt das hier ja auch.

    printf("SizeOf: %i\n",sizeof(long));
    

    Stimmt, es kommt 8 raus.



  • @SeppJ sagte in Ein "long" als String ?:

    @Mathuas sagte in Ein "long" als String ?:

    Dies verwundert mich, das dies ein grösserer Bug ist. Ein 32Bit Pointer auf einem 64Bit OS.

    Ich sehe da nix mit 32 Bit. long ist bei üblichen Linuxcompilern 64 Bit, deswegen klappt das hier ja auch.

    Auf Linux x86 ist sizeof(long) == sizeof(void*) .
    Vom Compiler unabhängig, da Teil der ABI.

    Mit MSVC ist sizeof(long) == 4.
    Ob das Teil der ABI ist, da kann man sich streiten, weil die Windows-Headers quasi überall typedefs verwenden. Also sizeof(LONG) == 4 muss gelten, aber die Frage ist ob LONG und long equivalent sein müssen.



  • @hustbaer sagte in Ein "long" als String ?:

    Auf Linux x86 ist sizeof(long) == sizeof(void*) .
    Vom Compiler unabhängig, da Teil der ABI.

    So wie es scheint, hat C das gleiche Problem wie Pascal, die Integer sind nicht einheitlich.
    Wie es bei Java, Python und co. weis ich nicht.


  • Mod

    Es ist schon einheitlich, aber in einem anderen Sinne als eine feste Bitbreite: Als der passendste Typ für die Maschine. Das ist kein Nachteil, sondern ein Vorteil auf einem anderen Gebiet als du dir wünscht. Wenn du feste Bitbreiten willst, musst du eben einen der dafür vorgesehenen Typdefs benutzen. Die halt nicht unbedingt existieren, sondern nur, wenn es die auf der Maschine tatsächlich gibt. Womit man auch einen Teil des Vorteils erkennt: Ein typisches C-Programm, das nicht absichtlich die Typen mit fester Breite benutzt, läuft ohne Änderung auf Systemen mit 24-Bit Bytes. Ja, das gibt es. Ist halt relevant für Sprachen, die auch zur Programmierung von Supercomputern oder Microcontrollern gedacht ist.

    PS: Weil mich dafür Beispiele interessierten (sind aber zu viele für eine Liste), hier ein besonders interessanter Fall: Die DEC-10 hatte sogar eine Variable Bytebreite von 1-36. Der GCC hat angeblich Unterstützung für diese Maschine. Aber meine Energie reicht gerade nicht für eine Recherche, was dort als CHAR_BITS oder sizeof(int) definiert ist (Der Link zum ABI ist leider tot).



  • @Mathuas sagte in Ein "long" als String ?:

    Wie es bei Java, Python und co. weis ich nicht.

    Bei Python hat int keine Beschränkung (ist also ein bigint).

    $ echo 'print(f"{2 ** 100 = }")' | python
    2 ** 100 = 1267650600228229401496703205376
    

    Aber wieder natürlich mit interessanten Features wie dass kleine gleiche Zahlen auf dasselbe Objekt zeigen können, große gleiche aber nicht.

    >>> j1=10234
    >>> j2=10234
    >>> j1 is j2
    False
    >>> i1=5
    >>> i2=5
    >>> i1 is i2
    True
    


  • @SeppJ sagte in Ein "long" als String ?:

    Es ist schon einheitlich, aber in einem anderen Sinne als eine feste Bitbreite: Als der passendste Typ für die Maschine.

    Für Java stimmt dies nicht. Dort umfasst ein

    • int immer 4 Byte,
    • long immer 8 Byte,
    • char immer 2 Byte, (vorzeichenlos)
    • short immer 2 Byte,
    • byte immer 1 Byte,
    • float immer 4 Byte,
    • und double immer 8 Byte.

    Und wie das intern technisch realisiert worden ist, das ist ein Implementierungsdetail der JVM und für den normalen Programmierer im Normalfall völlig irrelevant. Dieser muss nur den gültigen Wertebereich kennen.

    Java ist (sehr) streng typisiert.



  • Oder ... um ganz genau zu sein: statisch, explizit und implizit, stark typisiert; siehe auch hier: https://de.wikipedia.org/wiki/Typisierung_(Informatik)#Beispiele



  • @Fragender sagte in Ein "long" als String ?:

    @SeppJ sagte in Ein "long" als String ?:

    Es ist schon einheitlich, aber in einem anderen Sinne als eine feste Bitbreite: Als der passendste Typ für die Maschine.

    Für Java stimmt dies nicht. Dort umfasst ein

    • int immer 4 Byte,
    • long immer 8 Byte,
    • char immer 2 Byte, (vorzeichenlos)
    • short immer 2 Byte,
    • byte immer 1 Byte,
    • float immer 4 Byte,
    • und double immer 8 Byte.

    Und wie das intern technisch realisiert worden ist, das ist ein Implementierungsdetail der JVM und für den normalen Programmierer im Normalfall völlig irrelevant. Dieser muss nur den gültigen Wertebereich kennen.

    Java ist (sehr) streng typisiert.

    Ausser man verwendet einen Vertexpuffer von OpenGL, dann ist die Datenbreite auf einmal sehr wichtig.



  • @Mathuas sagte in Ein "long" als String ?:

    Ausser man verwendet einen Vertexpuffer von OpenGL, dann ist die Datenbreite auf einmal sehr wichtig.

    Nein, ist es nicht. OpenGL gehört nicht zu Java.



  • @hustbaer sagte in Ein "long" als String ?:

    Auf Linux x86 ist sizeof(long) == sizeof(void*) .
    Vom Compiler unabhängig, da Teil der ABI.

    Das ist nicht nur auf Linux x86 der Fall, sondern auf jedem OS, dass sich an die Single UNIX Specification hält. Diese definiert nämlich für den 32Bit Modus ILP32 und für den 64Bit Modus LP64. Es gab zwar Abweichungen von der SUS (klassisches UNICOS auf Cray Hardware nutzte SILP64), aber diese sind mittlerweile nur noch als historisch zu bezeichnen, da diese OS keinerlei Rolle mehr spielen.



  • @Fragender sagte in Ein "long" als String ?:

    @Mathuas sagte in Ein "long" als String ?:

    Ausser man verwendet einen Vertexpuffer von OpenGL, dann ist die Datenbreite auf einmal sehr wichtig.

    Nein, ist es nicht. OpenGL gehört nicht zu Java.
    Es ist nicht direkt in Java, aber man kann es einbinden, so wie es bei fast jeder Sprache möglich ist.

    Bei Android ist man fast auf das Gespann Java und OpenGL/SE angewiesen.



  • Das ist aber etwas anderes. Wenn man OpenGL verwenden möchte, nimmt man in 99,99 % der Fälle C++...

    Du würdest doch auch nicht versuchen wollen, in JavaScript Assembler zu programmieren...



  • @Fragender sagte in Ein "long" als String ?:

    Das ist aber etwas anderes. Wenn man OpenGL verwenden möchte, nimmt man in 99,99 % der Fälle C++...

    Du würdest doch auch nicht versuchen wollen, in JavaScript Assembler zu programmieren...

    Das stimmt schon, auf dem PC würde ich auch kein Java für OpenGL nehmen, sondern Pascal, oder wie du sagst C/C++.
    Aber bei Android ist dies ein Sonderfall.
    Assembler und OpenGL kann man schlecht vergleichen. Assembler ist Maschienensprache, Und OpenGL eine Schnittstelle zu Hardware.
    Wen bei OpenGL mal die Daten im VRAM sind, läuft eine Animation auch mit Python angenehm schnell. Die Hardware Beschleunigung ist immer gleich schnell. Aussgenommen WebGL, da läuft nur ein Warper.


Anmelden zum Antworten