Verständnisfrage C: Pointer in structs

mogbo

Banned
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
 
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.
 
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;
 
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);
 
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:
Ist notiert, hab ich leider noch nicht gekannt.

mir ist das Problem nicht ganz klar. Deswegen beschreibe ich mal, was an den entscheidenden Stellen passiert.
Du hast nicht mehr und nicht weniger wie genau das erklärt, was ich wissen wollte :)

1. was verstehst Du nicht?:confused:
Das was @marcel erklärt hat

2. wer lehrt solche Unfug-Deklarationen? :D
Ich, war aber nur Beispielcode :ugly:
 
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.
 
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.
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
 
Zurück
Oben