Wie funktioniert memset?



  • Big Brother schrieb:

    MFK schrieb:

    Oder einfach gar nichts tun, weil jeder Zeiger implizit in void* konvertierbar ist. Du baust einen Zaubertrick um etwas, das von ganz allein passiert.

    Der Zaubertrick ist ein gewöhnliches Sprachmittel von C, ein Cast. Das die Umwandlung automatisch geschieht, wird wohl so sein, letztlich ist ja nur die Adresse von Bedeutung.

    MFK schrieb:

    Was sagt denn dein Compiler, wenn du den Cast weglässt?

    Der sagt mir alles ok. Den interessiert nicht, ob ich nen Zeiger auf int übergebe, oder ob ich den Zeiger gemäß memset - Deklaration nach void caste.
    Wenn ich Zeit übrig habe, gucke ich mal nach, ob der Draft etwas dazu sagt.

    Naja, man kann des Cast schon machen, aber er ist absolut überflüssig und in der Regel nicht zu empfehlen. Der einzige Fall, wo es Sinn macht, ist wenn man C-Code in einem C++ Projekt übersetzen will. C++ fordert nämlich den Cast.



  • kzH schrieb:

    sorry, wenn ich mich als newbie hier einmische, aber für mich macht "memset" nur bei Zeichenketten oder zum "Ausnullen" Sinn.

    char sz[] = "Hallo Welt";
    int test[10];
    memset(sz, 'a', strlen(sz));
    memset(test,0,sizeof(test));
    

    Wenn ich ein int - Array mit "sinnvollen" Werten füllen will, bleibt meines Erachtens nur, Wert für Wert zu setzen.

    ganz richtig^^
    ints sind meistens grösser als chars und weil memset den speicher als eine folge von 'unsigned chars' betrachtet, haut das voll nicht hin.
    🙂



  • kzH schrieb:

    sorry, wenn ich mich als newbie hier einmische, aber für mich macht "memset" nur bei Zeichenketten oder zum "Ausnullen" Sinn.

    char sz[] = "Hallo Welt";
    int test[10];
    memset(sz, 'a', strlen(sz));
    memset(test,0,sizeof(test));
    

    Dies ist kein Forum für Fortgeschrittene.

    kzH schrieb:

    Wenn ich ein int - Array mit "sinnvollen" Werten füllen will, bleibt meines Erachtens nur, Wert für Wert zu setzen.
    Oder? 😕

    Ja, genau. Alles andere ist Frickelunsinn.


  • Mod

    Der Cast ist bloß überflüssig, auch in C++. Das genügt nicht, um das Ganze als Unfug zu qualifizieren. Allerdings fällt es schwer, mit der Ignoranz umzugehen, die Arrays und Zeiger durcheinander würfelt und gleichzeitig noch auf dem Umgang mit dem exakten Zeigertyp besteht.
    Arrays sind keine Zeiger. Arrays sind keine Zeiger. Arrays sind keine Zeiger.
    Ein Array kann überall benutzt werden, wo ein Zeiger erwartet. Ebenso wie z.B. ein int benutzt werden kann, wo ein double erwarte wird. Das bedeutet aber natürlich nicht, dass int und double identisch wären. Ein Objekt oder Ausdruck hat stets einen eindeutig bestimmten Typen, da Zeiger und Arrays verschiedene Typen sind, kann weder ein Objekt noch ein Ausdruck gleichzeitig Array und Zeiger sein. Es wäre wirklich schön, wenn solche Diskussionen gelegentlich auf erworbenem Wissen und nicht nur auf Hörensagen und Vermutungen beruhen würden - ebenso wie etwa die völlig überflüssige Bemerkung bzgl. Casts in C++ (was wirklich nicht so kompliziert ist, dass man sich nicht zuerst darüber sicheres Wissen aneignen könnte). Komischerweise sind es nämlich immer gerade diese, die von Anfängern aufgeschnappt werden - und man verschwendet dann Zeit, diesen Eindruck erst einmal korrigieren zu müssen.



  • Tachyon schrieb:

    Der einzige Fall, wo es Sinn macht, ist wenn man C-Code in einem C++ Projekt übersetzen will. C++ fordert nämlich den Cast.

    besser: dann compiliert man den c-code trotzdem mit 'nem c-compiler und der linker erledigt den rest.
    🙂



  • ansiC bad ass schrieb:

    Tachyon schrieb:

    Der einzige Fall, wo es Sinn macht, ist wenn man C-Code in einem C++ Projekt übersetzen will. C++ fordert nämlich den Cast.

    besser: dann compiliert man den c-code trotzdem mit 'nem c-compiler und der linker erledigt den rest.
    🙂

    Genau für diesen Fall gibt es überhaupt keine Kompatibilitätsprobleme zwischen C und C++. Ein C Compiler ist also hier nicht von nöten. 🙂



  • David_pb schrieb:

    ansiC bad ass schrieb:

    Tachyon schrieb:

    Der einzige Fall, wo es Sinn macht, ist wenn man C-Code in einem C++ Projekt übersetzen will. C++ fordert nämlich den Cast.

    besser: dann compiliert man den c-code trotzdem mit 'nem c-compiler und der linker erledigt den rest.
    🙂

    Genau für diesen Fall gibt es überhaupt keine Kompatibilitätsprobleme zwischen C und C++. Ein C Compiler ist also hier nicht von nöten. 🙂

    für den fall vielleicht nicht, aber generell ist es keine besonders gute idee, C code durch einen c++ compiler zu scheuchen.
    🙂



  • ansiC bad ass schrieb:

    David_pb schrieb:

    ansiC bad ass schrieb:

    Tachyon schrieb:

    Der einzige Fall, wo es Sinn macht, ist wenn man C-Code in einem C++ Projekt übersetzen will. C++ fordert nämlich den Cast.

    besser: dann compiliert man den c-code trotzdem mit 'nem c-compiler und der linker erledigt den rest.
    🙂

    Genau für diesen Fall gibt es überhaupt keine Kompatibilitätsprobleme zwischen C und C++. Ein C Compiler ist also hier nicht von nöten. 🙂

    für den fall vielleicht nicht, aber generell ist es keine besonders gute idee, C code durch einen c++ compiler zu scheuchen.
    🙂

    Habe ich auch nicht behauptet und würde ich auch nicht machen. War nur der einzige Fall, wo man das überhaupt machen müsste.
    Mir würde im Traum nicht einfallen, void-Pointer zu casten, weils einfach Schwachsinn ist.



  • Tachyon schrieb:

    Mir würde im Traum nicht einfallen, void-Pointer zu casten, weils einfach Schwachsinn ist.

    sehr gut. das musste mal wieder gesagt werden. 👍
    🙂



  • ansiC bad ass schrieb:

    Tachyon schrieb:

    Mir würde im Traum nicht einfallen, void-Pointer zu casten, weils einfach Schwachsinn ist.

    sehr gut. das musste mal wieder gesagt werden. 👍
    🙂

    Schwachsinn. 👎

    Dafür sind die typenlosen void Zeiger doch da, um gecastet und zur Laufzeit an einen Datentypen gebunden zu werden.

    void* pv;
    	int i = 10;
    	char a = 'a';
    	pv = &i;
     	printf("%d\n",  *(int*)pv ); // void Zeiger nach int* gecastet und dereferenziert.
    	pv = &a;
     	printf("%c\n", *(char*)pv ); // void Zeiger nach char* gecastet und dereferenziert.
    

    🙄



  • Mr. Rolleyes schrieb:

    ansiC bad ass schrieb:

    Tachyon schrieb:

    Mir würde im Traum nicht einfallen, void-Pointer zu casten, weils einfach Schwachsinn ist.

    sehr gut. das musste mal wieder gesagt werden. 👍
    🙂

    Schwachsinn. 👎

    Dafür sind die typenlosen void Zeiger doch da, um gecastet und zur Laufzeit an einen Datentypen gebunden zu werden.

    void* pv;
    	int i = 10;
    	char a = 'a';
    	pv = &i;
     	printf("%d\n",  *(int*)pv ); // void Zeiger nach int* gecastet und dereferenziert.
    	pv = &a;
     	printf("%c\n", *(char*)pv ); // void Zeiger nach char* gecastet und dereferenziert.
    

    🙄

    Ist das so? Ich dachte immer, die sind für generische Algorithmen, wo der Typ des übergebenen Objektes keine Rolle spielt.
    Mal davon abgesehen bindet der Compiler den Typen schon für Dich. Da muss man nichts casten.

    EDIT: Dein Beispiel ist realitätsfern...



  • Mr. Rolleyes schrieb:

    void* pv;
    	int i = 10;
    	char a = 'a';
    	pv = &i;
     	printf("%d\n",  *(int*)pv ); // void Zeiger nach int* gecastet und dereferenziert.
    	pv = &a;
     	printf("%c\n", *(char*)pv ); // void Zeiger nach char* gecastet und dereferenziert.
    

    🙄

    das ist zwar richtig, aber wer mit genügend Menschenverstand wird so einen Code schreiben? Der Code ist so als würde ich auf einer Gerade laufen und dabei mich noch um die eigene Achse drehen. Klar geht das auch, aber ist völlig unnötig. 🙄



  • Mr. Rolleyes schrieb:

    Dafür sind die typenlosen void Zeiger doch da, um gecastet und zur Laufzeit an einen Datentypen gebunden zu werden.

    aber ohne cast:

    void *slow_memset (void *s, int c, size_t n)
    {
      unsigned char *p = s;  // <--- kein cast!
      while (n--)
        *p++ = c;
      return s;
    }
    

    🙂



  • ansiC bad ass schrieb:

    Mr. Rolleyes schrieb:

    Dafür sind die typenlosen void Zeiger doch da, um gecastet und zur Laufzeit an einen Datentypen gebunden zu werden.

    aber ohne cast:

    void *slow_memset (void *s, int c, size_t n)
    {
      unsigned char *p = s;  // <--- kein cast!
      while (n--)
        *p++ = c;
      return s;
    }
    

    🙂

    So gehts ohne Cast, nur bei C++ müsste man das casten, aber fürs Dereferenzieren brauchste den Cast!

    printf("%d\n",  *(int*)pv ); // <-- Doch Cast !
    

    🙂

    supertux schrieb:

    Mr. Rolleyes schrieb:

    void* pv;
    	int i = 10;
    	char a = 'a';
    	pv = &i;
     	printf("%d\n",  *(int*)pv ); // void Zeiger nach int* gecastet und dereferenziert.
    	pv = &a;
     	printf("%c\n", *(char*)pv ); // void Zeiger nach char* gecastet und dereferenziert.
    

    🙄

    das ist zwar richtig, aber wer mit genügend Menschenverstand wird so einen Code schreiben? Der Code ist so als würde ich auf einer Gerade laufen und dabei mich noch um die eigene Achse drehen. Klar geht das auch, aber ist völlig unnötig. 🙄

    Das ist doch nur ein Beispiel für die Benutzung, das das in diesem Beispielfall nicht viel Sinn hergibt ist doch klar und steht doch gar nicht zur Diskussion 🙄 🙄



  • Mr. Rolleyes schrieb:

    So gehts ohne Cast, nur bei C++ müsste man das casten, aber fürs Dereferenzieren brauchste den Cast!

    1. void* kann man nicht dereferenzieren.
    2. C++ ist absolut entbehrlich.
    🙂



  • Mr. Rolleyes schrieb:

    Das ist doch nur ein Beispiel für die Benutzung, das das in diesem Beispielfall nicht viel Sinn hergibt ist doch klar und steht doch gar nicht zur Diskussion 🙄 🙄

    ist trotzdem ein schlechtes Beispiel, denn damit "beweist" du deine These nicht. Und dass man einen void Zeiger nicht dereferenzieren kann (außer mit Hilfe eines Casts [1]) ist eine völlig andere Geschichte (und hat nichts mit deiner These zu tun).

    edit:
    [1]
    selbst das brauchst du nicht. Ich nehme dein eigenes Bsp:

    void* pv; 
        int i = 10; 
        char a = 'a';
    
        pv = &i;
        int *int_ptr = pv;
        printf("%d\n",  *int_ptr ); 
    
        pv = &a;
        char *char_ptr = pv;
        printf("%c\n", *char_ptr );
    

    😉



  • ansiC bad ass schrieb:

    Mr. Rolleyes schrieb:

    So gehts ohne Cast, nur bei C++ müsste man das casten, aber fürs Dereferenzieren brauchste den Cast!

    1. void* kann man nicht dereferenzieren.
    2. C++ ist absolut entbehrlich.
    🙂

    Zu 1.)
    Das ist richtig! Deshalb muss man den void Zeiger vorher in den entsprechenden Datentypen casten.
    Für Dich schreibe ich es gern noch einmal hin:

    printf("%d\n",  *(int*)pv ); // Cast nach int* und dereferenziert
    

    🙂

    Zu 2.)
    Weiß nicht.
    Das kann man im grunde genommen von jeder Programmiersprache sagen.



  • supertux schrieb:

    ist trotzdem ein schlechtes Beispiel, denn damit "beweist" du deine These nicht.

    Welche These? 😕

    supertux schrieb:

    void* pv; 
        int i = 10; 
        char a = 'a';
        
        pv = &i;
        int *int_ptr = pv;
        printf("%d\n",  *int_ptr ); 
    
        pv = &a;
        char *char_ptr = pv;
        printf("%c\n", *char_ptr );
    

    Was ist das denn für ein Gurkenbeispiel, da kann man doch völlig auf den void Zeiger verzichten.
    Die Verwendung des Zeigers sollte aber gezeigt werden. :p



  • Mr. Rolleyes schrieb:

    Zu 1.)
    Das ist richtig! Deshalb muss man den void Zeiger vorher in den entsprechenden Datentypen casten.

    damit dereferenziert man aber keinen void* mehr, sondern er wird als pointer auf einen anderen typ angesehen. das ist ein feiner unterschied.
    das hier:

    long a = 7;
    *(char*)a = 10;
    

    dereferenziert nicht etwa eine long-variable, sondern ihr inhalt (die 7) wird als 'char-pointer' interpretiert.

    Mr. Rolleyes schrieb:

    Zu 2.)
    Weiß nicht.
    Das kann man im grunde genommen von jeder Programmiersprache sagen.

    auf manche sprachen trifft es aber eher zu als auf andere.
    🙂



  • ansiC bad ass schrieb:

    damit dereferenziert man aber keinen void* mehr, sondern er wird als pointer auf einen anderen typ angesehen. das ist ein feiner unterschied.

    Weil er vorher in den entsprechenden Zeigertypen gecastet wird, da bin ich ganz deiner Meinung.

    ansiC bad ass schrieb:

    das hier:

    long a = 7;
    *(char*)a = 10;
    

    dereferenziert nicht etwa eine long-variable, sondern ihr inhalt (die 7) wird als 'char-pointer' interpretiert.

    Das ist allerdings, ehm... Käse.
    🙂


Anmelden zum Antworten