zeiger auf zeiger aus einer struct



  • Hallo

    Ich möchte eine dynamischen vector implementieren in c.

    typedef struct {
      char **dynmem;
      size_t memlen;
    } DYNMEMVECTOR;
    

    wie greiffe ich jetzt in der funktion xy die ein zeiger auf das struct bekommt zu? wenn ich zum bsp mit realloc dein soicherbereich vergrössern will?

    int funcxy(DYNMEMVECTOR *dynmemptr)
    {

    // so ?
    *dynmemptr->dynmem = realloc(*dynmemptr->dynmem , lenx);

    ...
    ...


  • Mod

    -> bindet stärker als *. Das heißt *dynmemptr->dynmem bedeutet so viel wie *(dynmemptr->dynmem) .

    Wieso ist das denn ein Doppelzeiger? Sollte das nicht nur ein einfacher Zeiger sein? Existiert *dynmemptr->dynmem überhaupt?



  • Es ist ein doppel zeiger da ich sonnst den Speicher ja nicht erweitern kann mit (realloc)... poste später mein realles bsp. ca. 1h. gruss


  • Mod

    memuser schrieb:

    Es ist ein doppel zeiger da ich sonnst den Speicher ja nicht erweitern kann mit (realloc)

    😕 realloc funktioniert anders.



  • int DynMemCat(DYNMEMVECTOR *ptrdynmem ,const char *srcmem ,size_t srclen )
    {
    	size_t currentlen = 0 ,srcstrlen = 0;
    	char **mem = NULL;
    
    	mem = &(ptrdynmem->ptrdynmem);
    
    	if( srcmem == 0 )
    		return 0;
    	if( *srcmem == 0 )
    		return 0;
    
    	if( *mem == NULL ) {
    	  	*mem = calloc(1 ,1);
    		if(*mem == NULL)
    			return 0;
    		ptrdynmem->dynmemlen = 1;
    	}
    
    	*mem = realloc(*mem ,ptrdynmem->dynmemlen+srclen);
    	if(*mem == NULL)
    		return 0;
    
    	memcpy(*mem+ptrdynmem->dynmemlen ,srcmem ,srcstrlen);
    
    	ptrdynmem->dynmemlen += srclen;
    
    	return 1;
    }
    
    typedef struct {
    
    	char **ptrdynmem;
    	size_t dynmemlen;
    
    } DYNMEMVECTOR;
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "memlibc.h"
    
    int main(void)
    {
    	DYNMEMVECTOR memptr = {0};
    	char str1[] = {66,66,0x65,0x65,0x65,0x65,0x65};
    	char str2[] = {0x02,0x02,0x02,0x02,0x02,0x02,0x02};
    
    	DynMemCat(&memptr ,str1 ,7);
    	DynMemCat(&memptr ,str1 ,7);
    
    	printf("%c",memptr.ptrdynmem);   <- elemet 0 hat nicht 66
    
    	FreeDynMemCat(&memptr);
    
    	getchar();
    
    	return 0;
    }
    

    Bekomme falsche werte?



  • Warum sollte in memptr.ptrdynmem die 66 stehen?
    memptr.ptrdynmem ist ein char**. %c (bei printf) dient zur Ausgabe von char (int).
    Großer Unterschied.
    Das sagt mein Compiler dazu:
    main.c|16|warning: format '%c' expects argument of type 'int', but argument 2 has type 'char **' [-Wformat]|

    char *z;  //   *z ist das char,   z ist der Zeiger auf char
    char *zz; // **zz ist das char, *zz ist ein Zeiger auf char, zz ist ein Zeiger auf einen Zeiger auf char
    

    Deine Funktion DynMemCat ist ein großes Zeigerdurcheinander.

    int DynMemCat(DYNMEMVECTOR *ptrdynmem ,const char *srcmem ,size_t srclen )
    {
        size_t currentlen = 0 ,srcstrlen = 0;
        char **mem = NULL;
    
        mem = &(ptrdynmem->ptrdynmem);  //assignment from incompatible pointer type [enabled by default]|
    // &(ptrdynmem->ptrdynmem) ist die Adresse von ptrdynmem, nicht das worauf es zeigt. es ist ein char***
    
        if( srcmem == 0 )  // Da wäre NULL verständlicher
            return 0;
        if( *srcmem == 0 ) // Das hat nur Sinn, wenn srcmem auf einen C-String zeigt
            return 0;      // Tut es aber nicht, da die Nullterminierung fehlt.
    
        if( *mem == NULL ) {
            *mem = calloc(1 ,1); // Warum ?
            if(*mem == NULL)
                return 0;
            ptrdynmem->dynmemlen = 1;  //??
        }
    
        *mem = realloc(*mem ,ptrdynmem->dynmemlen+srclen);  
        if(*mem == NULL)   
            return 0;
    
        memcpy(*mem+ptrdynmem->dynmemlen ,srcmem ,srcstrlen); // selbst wenn das bis hier klappt, schreibst du die Zeichen durch das calloc erst ab Index 1 in den Speicher.
     // Auch deswegen kann da nicht die 66 stehen.
    
        ptrdynmem->dynmemlen += srclen;
    
        return 1;
    }
    

    Und die Doppelzeiger (mem und ptrdynmem) sind hier total überflüssig.
    Mach einfache Zeige daraus.
    (Und vergiss nicht, den Wert von mem wieder in der struct abzulegen.)

    Lass das calloc weg.
    realloc verhält sich wie malloc , wenn der erste Parameter NULL ist.



  • Hallo

    Danke DirkB jetzt habe ich es begriffen. 👍



  • Hallo

    Habe ich jetzt das so richtig verstanden?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct {
    
    	char **ptrdynmem;
    	size_t dynmemlen;
    
    } DYNMEMVECTOR;
    
    int DynMemCat(DYNMEMVECTOR *ptrdynmem ,const char *srcmem ,size_t srclen )
    {
    
    	if( srcmem == 0 )
    		return 0;
    
    	ptrdynmem->ptrdynmem = realloc(ptrdynmem->ptrdynmem ,ptrdynmem->dynmemlen+srclen);
    	if(ptrdynmem->ptrdynmem == NULL)
    		return 0;
    
    	memcpy(ptrdynmem->ptrdynmem+ptrdynmem->dynmemlen ,srcmem ,srclen);
    
    	ptrdynmem->dynmemlen += srclen;
    
    	return 1;
    }
    
    void FreeDynMemCat(DYNMEMVECTOR *ptrdynmem)
    {
    	free(ptrdynmem->ptrdynmem);
    	return;
    }
    
    int main(void)
    {
    	DYNMEMVECTOR memptr = {0};
    
    	char str1[] = {66,66,66,66,66,66,66};
    	char str2[] = {66,66,66,66,66,66,66};
    
    	DynMemCat(&memptr ,str1 ,7);
    	DynMemCat(&memptr ,str2 ,7);
    
    	printf("%c",memptr.ptrdynmem[0]);
    
    	FreeDynMemCat(&memptr);
    
    	getchar();
    
    	return 0;
    }
    


  • Nein! So wäre es richtig...

    typedef struct {
    
    	char *ptrdynmem;    // Einfacher char zeiger
    	size_t dynmemlen;
    
    } DYNMEMVECTOR;
    
    int DynMemCat(DYNMEMVECTOR *ptrdynmem ,const char *srcmem ,size_t srclen )
    {
    
    	if( srcmem == 0 )
    		return 0;
    
    	ptrdynmem->ptrdynmem = realloc(ptrdynmem->ptrdynmem ,ptrdynmem->dynmemlen+srclen);
    	if(*ptrdynmem->ptrdynmem == NULL)
    		return 0;
    
    	memcpy(ptrdynmem->ptrdynmem+ptrdynmem->dynmemlen ,srcmem ,srclen);
    
    	ptrdynmem->dynmemlen += srclen;
    
    	return 1;
    }
    
    void FreeDynMemCat(DYNMEMVECTOR *ptrdynmem)
    {
    	free(ptrdynmem->ptrdynmem);
    	return;
    }
    
    int main(void)
    {
    	DYNMEMVECTOR memptr = {0};
    
    	char str1[] = {66,66,66,66,66,66,66};
    	char str2[] = {66,66,66,66,66,66,66,0}; // zur Demo
    
    	DynMemCat(&memptr ,str1 ,7);
    	DynMemCat(&memptr ,str2 ,8);
    
    	printf("%s",memptr.ptrdynmem); // und so greifst du auf den Speicher zu. Funktioniert hier mit %s weil str2 am ende eine 0 Terminierung hat.
    
    	FreeDynMemCat(&memptr);
    
    	getchar();
    
    	return 0;
    }
    


  • memuser schrieb:

    typedef struct {
     
        char **ptrdynmem;
        size_t dynmemlen;
     
    } DYNMEMVECTOR;
    ...
    printf("%c",memptr.ptrdynmem[0]);
    

    So war es gemeint. Beim zz ist der zweite * abhanden gekommen

    char  *z;  //   *z ist das char,   z ist der Zeiger auf char
    char **zz; // **zz ist das char, *zz ist ein Zeiger auf char, zz ist ein Zeiger auf einen Zeiger auf char
    

    Ein Arrayzugriff ersetzt einen *
    Also ist

    char **zz; // zz[0][0] ist das char, zz[0] ist ein Zeiger auf char, zz ist ein Zeiger auf einen Zeiger auf char
    

    memptr.ptrdynmem[0] ist bei dir daher immer noch ein char* und kein char

    Die Variable mem war aber nicht so verkehrt.
    Das gilt für die Version von -lowbyte- (mit einfachem Zeiger):

    int DynMemCat(DYNMEMVECTOR *ptrdynmem ,const char *srcmem ,size_t srclen )
    {
        char *mem = ptrdynmem->ptrdynmem;
    
        if( srcmem == NULL )
            return 0;
    
        mem = realloc(ptrdynmem->ptrdynmem ,ptrdynmem->dynmemlen+srclen);
        if(mem == NULL)
            return 0;  // so bleibt im Fehlerfall noch alles beim alten
        ptrdynmem->ptrdynmem = mem;
        memcpy(ptrdynmem->ptrdynmem+ptrdynmem->dynmemlen ,srcmem ,srclen);
    
        ptrdynmem->dynmemlen += srclen;
    
        return 1;
    }
    

    Und mit einfachem Zeiger für ptrdynmem, klappt auch

    printf("%c",memptr.ptrdynmem[0]);
    


  • Das alles stimmt aber nur für die Annahme, dass der Frager mit "Vektor" eine Folge von Zeichen/Bytes meint und nicht eine Folge von Zeichenketten/Bytearrays.
    Bei Letzterem wäre dann char** OK.


Anmelden zum Antworten