1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

Verständnisfrage C: Pointer in structs

Dieses Thema im Forum "Programmieren" wurde erstellt von mogbo, 5 Januar 2018.

  1. mogbo

    mogbo Does it run under Windows? Who cares?

    Registriert seit:
    12 September 2016
    Beiträge:
    722
    Hallo,
    wiedermal eine Frage die ich nicht wirklich ergoogelt bekomme:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct node {
      int zahl;
      struct node *next;
    } node_t;
    
    node_t *ptr = NULL;
    
    
    
    int
    main(void)
    {
      short i = 0, b = 3;
    
      ptr = malloc(sizeof(node_t));
      node_t *current = ptr;
    
      ptr->zahl = i;
    
      i++;
    
      /* Struct fuell-Schleife */
      while (i <= b) {
          ptr->next = malloc(sizeof(node_t));
          ptr->next->zahl = i;
    
          /*
           * Gebe ich hier wirklich die Position von ptr->next->zahl aus?
           */
          printf("Position von ptr->next->zahl: %p\n", &(ptr->next->zahl));
          printf("Position von ptr->next->zahl: %p\n\n", ptr->next);
          // Ende der Frage 1
    
          /*
           * Wie gebe ich die Position von "next" aus?
           */
          printf("Position von ptr->next: %p\n", &(ptr->next));
          ptr = ptr->next;
          printf("Position von ptr->next: %p\n\n", &ptr);
          // Ende der Frage 2
    
          i++;
      }
    
      ptr = NULL;
    
      printf("\nOutput:\n\n");
    
      /* Struct output-Schleife */
      while (current != NULL) {
          printf("%i\n", current->zahl);
          current = current->next;
      }
    
      free(ptr);
    
      return 0;
    }
    
    Siehe Comments in der 1. Schleife

    Ich verstehe nicht wirklich wie ich Speicherpositionen innerhalb eines structs ausgeben kann oder ist oben alles richtig und ich habe einen allgemeinen Denkfehler?

    Output:
    Code:
    Position von ptr->next->zahl: 0x1660f9b349f0
    Position von ptr->next->zahl: 0x1660f9b349f0
    
    Position von ptr->next: 0x16619afeace8
    Position von ptr->next: 0x165ec1301058
    
    Position von ptr->next->zahl: 0x166133268c70
    Position von ptr->next->zahl: 0x166133268c70
    
    Position von ptr->next: 0x1660f9b349f8
    Position von ptr->next: 0x165ec1301058
    
    Position von ptr->next->zahl: 0x1661269803b0
    Position von ptr->next->zahl: 0x1661269803b0
    
    Position von ptr->next: 0x166133268c78
    Position von ptr->next: 0x165ec1301058
    
    
    Output:
    
    0
    1
    2
    3
    
     
  2. nakal

    nakal Anfänger

    Registriert seit:
    12 September 2004
    Beiträge:
    2.105
    Es sieht so aus, als ob der Pointer des structs und des ersten Member zahl den gleichen Wert hat. Der Member zahl steht halt an Offset 0 im struct. Wenn Du die Member zahl und next vertauschst, dann wirst Du wahrscheinlich einen Unterschied sehen.
     
    mogbo gefällt das.
  3. Vril

    Vril Active Member

    Registriert seit:
    4 August 2016
    Beiträge:
    391
    mogbo gefällt das.
  4. das.chaos

    das.chaos Duracellhase 2.0

    Registriert seit:
    16 April 2008
    Beiträge:
    432
    Ort:
    Flensburg
    Hi,

    Fuer das Implementieren von rekursiven Datenstrukturen [verkett. Listen, Queues, ...] sollte mMn vornehmlich die vom OS zur ferfuegung gestellte API verwendet werden. Beispiel aus queue(3) bzw. bereits verlinkte Manual Page:
    Code:
         SLIST_HEAD(slisthead, entry) head =
    	 SLIST_HEAD_INITIALIZER(head);
         struct slisthead *headp;		     /*	Singly-linked List head. */
         struct entry {
    	     ...
    	     SLIST_ENTRY(entry)	entries;     /*	Singly-linked List. */
    	     ...
         } *n1, *n2, *n3, *np;
    
         SLIST_INIT(&head);			     /*	Initialize the list. */
    
         n1	= malloc(sizeof(struct entry));	     /*	Insert at the head. */
         SLIST_INSERT_HEAD(&head, n1, entries);
    
         n2	= malloc(sizeof(struct entry));	     /*	Insert after. */
         SLIST_INSERT_AFTER(n1, n2,	entries);
    
         SLIST_REMOVE(&head, n2, entry, entries);/*	Deletion. */
         free(n2);
    
         n3	= SLIST_FIRST(&head);
         SLIST_REMOVE_HEAD(&head, entries);	     /*	Deletion from the head.	*/
         free(n3);
    					     /*	Forward	traversal. */
         SLIST_FOREACH(np, &head, entries)
    	     np-> ...
    					     /*	Safe forward traversal.	*/
         SLIST_FOREACH_SAFE(np, &head, entries, np_temp) {
    	     np->do_stuff();
    	     ...
    	     SLIST_REMOVE(&head, np, entry, entries);
    	     free(np);
         }
    
         while (!SLIST_EMPTY(&head)) {	     /*	List Deletion. */
    	     n1	= SLIST_FIRST(&head);
    	     SLIST_REMOVE_HEAD(&head, entries);
    	     free(n1);
         }
    
    wobei
    Code:
    #include <sys/queue.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    
    struct node;     /* forward declaration */
    
    struct node {
        int    nd_zahl;
        SLIST_ENTRY(node) nd_next;
    };
    SLIST_HEAD(nd_head, node) head =
    	 SLIST_HEAD_INITIALIZER(head);
    struct nd_head *ptr;
    
     
    mogbo gefällt das.
  5. marcel

    marcel Active Member

    Registriert seit:
    9 Juli 2017
    Beiträge:
    324
    Hallo @mogbo ,

    mir ist das Problem nicht ganz klar. Deswegen beschreibe ich mal, was an den entscheidenden Stellen passiert.

    Code:
    printf("Position von ptr->next->zahl: %p\n", &(ptr->next->zahl));
    Gibt die Speicheradresse aus, an der ptr->next->zahl gespeichert ist.

    Code:
    printf("Position von ptr->next->zahl: %p\n\n", ptr->next);
    Gibt die Speicheradresse aus, auf die ptr->next zeigt, also auf die Speicheradresse des ersten Elements (zahl) der Datenstruktur. Deswegen sind die Adressen &(ptr->next->zahl) und ptr->next gleich.

    Code:
    printf("Position von ptr->next: %p\n", &(ptr->next));
    Gibt die Speicheradresse aus, an der ptr->next gespeichert ist.

    Code:
    ptr = ptr->next;
    ptr zeigt jetzt auf die selbe Adresse wie ptr->next vor dieser Zuweisung.

    Code:
    printf("Position von ptr->next: %p\n\n", &ptr);
    Gibt die Adresse aus, an der die Variable ptr gespeichert ist. Um tatsächlich die Adresse auszugeben, an der ptr->next gespeichert ist, müsste es heissen:
    Code:
    ptr = &(ptr->next);
    printf("Position von ptr->next: %p\n\n", ptr);
    
     
    mogbo gefällt das.
  6. mogbo

    mogbo Does it run under Windows? Who cares?

    Registriert seit:
    12 September 2016
    Beiträge:
    722
    Ist notiert, hab ich leider noch nicht gekannt.

    Du hast nicht mehr und nicht weniger wie genau das erklärt, was ich wissen wollte :)

    Das was @marcel erklärt hat

    Ich, war aber nur Beispielcode :ugly:
     
  7. das.chaos

    das.chaos Duracellhase 2.0

    Registriert seit:
    16 April 2008
    Beiträge:
    432
    Ort:
    Flensburg
    Die als style(9) namentlich bekannte Manual-page stellt eine grobe "Richtlinie" dar, wobei ich mich selber selten daran halte. :)

    Bspw. ist das ein schoenes Beispiel fuer einen Hashtable via queue(3) API, der per sys/queue.h implementiert wurde, wobei die tree(3) API nicht zu verachten ist, die sich in sys/tree.h befindet.
     
    mogbo gefällt das.
  8. mogbo

    mogbo Does it run under Windows? Who cares?

    Registriert seit:
    12 September 2016
    Beiträge:
    722
    Mir gehts erstmal ums verstehen, sobald ich das Verständnis habe nutze ich natürlich die Bibliotheken, will ja kein Rad neu erfinden, finds nur immer zermürbend etwas zu nutzen, was ich nicht verstehe
     
  9. marcel

    marcel Active Member

    Registriert seit:
    9 Juli 2017
    Beiträge:
    324
    Freut mich :)