Structure within structure and pointer

Thread Starter

@vajra

Joined May 2, 2018
154
Dear all

I have defined a struct's like this -

Code:
struct s

{
    int *p;   
}
here p is pointer and p is member of structure s

we also defined a struct's like this -
Code:
struct s

{
   struct s *p;  //I don't understand this statement exactly what it does in structure ?  
    
}
we have pointer to a structure within structure itself

struct s *p; //I don't understand this statement exactly what it does in structure ?

can someone help me to understand that statement
 

BobTPH

Joined Jun 5, 2013
11,496
Just like your first example adds a member that is a pointer to an integer, your second example adds a member that is a pointer to the structure type itself.
There us no mystery or contradiction here. It is a useful construct as it allows you to make a linked list of structs, where struct contains a pointer to the next one in the list. Normally, there would be other members in the struct, it is not very useful as you have defined it.

Bob
 

Ian Rogers

Joined Dec 12, 2012
1,136
If you move to C++ classes always have a pointer to themselves... It's called "this" Used when several instances of the same class reside in your program... "this" points to the instance you are working with.. ( instance is the term used to specify a class type object )
 

Thread Starter

@vajra

Joined May 2, 2018
154
Just like your first example adds a member that is a pointer to an integer, your second example adds a member that is a pointer to the structure type itself.
Bob
I have created structure of student that store id and percentage of student

look at this code

C:
#include <stdio.h>


//We have difine structure of student that store id and percentage of student
struct student
{
     int id;
     float percentage;
};

int main(void)
{

     struct student record1;   // record1 is the member of structure (student)
     struct student *ptr;      // ptr is the member of structure (student)
   
     record1.id = 1;           //assign the id for record1
     record1.percentage = 60;  //assign the percentage for record1

     ptr = &record1;           // record1 is the member of structure  and we have assign address of record1 to pointer

         printf("Records of STUDENT1: \n");
         printf("  Id is: %d \n", ptr->id);
         printf("  Percentage is: %f \n\n", ptr->percentage);

     return 0;
}
Records of STUDENT1:
Id is: 1
Percentage is: 60.000000
 

BobaMosfet

Joined Jul 1, 2009
2,211
Dear all

I have defined a struct's like this -

Code:
struct s

{
    int *p;
}
here p is pointer and p is member of structure s

we also defined a struct's like this -
Code:
struct s

{
   struct s *p;  //I don't understand this statement exactly what it does in structure ?

}
we have pointer to a structure within structure itself

struct s *p; //I don't understand this statement exactly what it does in structure ?

can someone help me to understand that statement
The code you are referring to is a bad attempt by somone who is ignorant about how to make a structure reference it's own form (like for a linked list). DO NOT define structures that way. You're learning wrong. Others may tell you it's okay- it isn't. And it makes you code sloppier. The correct way to define a structure is:

Code:
typedef struct
   {
   int *o;
   }s;

s   myStructure;
The *ONLY* time you use 's' as a label at the top is when you need to reference the structure inside itself before the compiler has seen the complete definition! Which allows you to reference it this way:

Code:
typedef struct p
   {
   p  *nextS;
   p  *lastS;
   int *o;
   }s;

s   myStructure;
s   nextStructure;

myStructure.nextS = (s*)&nextStructure;
myStructure.lastS = NULL;
 

Thread Starter

@vajra

Joined May 2, 2018
154
There us no mystery or contradiction here. It is a useful construct as it allows you to make a linked list of structs, where struct contains a pointer to the next one in the list. Normally, there would be other members in the struct, it is not very useful as you have defined it.

Bob
Hi @BobTPH

I am creating one node for list

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef struct List
{
    char Name[20];
    int Marks;
    
    struct List *next;
} List;

  int main()
{
   struct List* head = NULL;
  
   head  = (struct List*) malloc(sizeof(struct List)); 
  
   head->Marks = 20;
   head->Name[30] = "Vajra";

  while (head != NULL)
  {
     printf(" %d ", head->Marks);
     printf(" %s ", head->Name);     
     head = head ->next;
  }
 
   return 0;
}
warning: assignment makes integer from pointer without a cast [-Wint-conversion]
head->Name[30] = "Vajra";
^
20 ÿ&╥

Why does code print ÿ&╥ instead of Vajra ?
 

BobTPH

Joined Jun 5, 2013
11,496
You are trying to assign the pointer to the 31st element of the array.

This is wrong for multiple reasons.

You are trying assign a pointer to a variable of type char.
To put data into the array Name, you need to use strcpy()

Bob
 

djsfantasi

Joined Apr 11, 2010
9,237
When a result is not as expected. I check for simple errors first...

I don’t like the line
head->Name[30]=“Vajra”;​

First, you’re assigning a char array to a byte (one specific location in a char array). I’d drop the “[30]” from the statement. I suspect this is the cause of the error.

Second, you define “Name” to be a char array with 20 chars. You are accessing the 30th position and have a boundary error. This results in memory corruption!

Which could result in the printing of those ‘strange’ characters.


Update: @BobTPH beat me to it!
 

BobTPH

Joined Jun 5, 2013
11,496
I suspect he put the subscript in because the compiler did not allow him to assign to the array.

As I said before, you cannot simply assign to an array variable in C. You need to use strcpy() or some other function.

Bob
 

Thread Starter

@vajra

Joined May 2, 2018
154
I was trying to make simple list to store student name's and marks. I am struggling to use strcpy() in my previous post

now I just want list to store only marks of students

C:
#include <stdlib.h>
#include <string.h>

typedef struct List
{
   
    int Marks;
   
    struct List *next;
   
} List;

  int main()
{
   struct List* head = NULL;

   head  = (struct List*) malloc(sizeof(struct List));

   head->Marks = 20;

   printf(" %d ", head->Marks);
     
   return 0;
}
Now I can only store marks of one student if I don't know the number of students so How to make list for n students to store their marks ?
 

djsfantasi

Joined Apr 11, 2010
9,237
To add another student, you need to allocate another variable of type List. Right now, there is no place to put another student.

But you should now be concerned that it appears that you need as many separate variables as students.

The simple solution is to define an array of type List. Then you can access each record the same way you’d select an element of a one-dimensional array.It might be good to test this approach. Start with a small number of students, because you have to hard-code the number of students. But this wastes memory space for the List struct for any unused student records.

Your structure already has a way of traversing the list. You are trying to use a linked list and it appears you don’t understand the concepts. When you allocate the first record, save the pointer to the struct,
firstRec = * head;
When you add more records, you must update a pointer variable with the value of the added records pointer, lastRec. AND, you must add that pointer to the previous record’s next field.

Now, by starting at the List struct with the *firstRec pointer, you can get the next record by extracting the next record’s pointer from the record current in use. Repeat until the record pointer equals the pointer value in the last record pointer, lastRec.

This conserves memory, but scanning the list is more difficult. May I suggest using Student as type int for now, until you get this part working.

Using this approach, your type definition for list would look like this;
Code:
typedef struct List
{ int studentNum;
  int Marks;
  int* next;
}
At a small increase in memory, you might find adding a “prev” field might be useful.

This method will also let you insert new student records in alphabetical order, without shifting memory all over the place. Research List Processing on your own.

I’m writing this from memory, so I may have made some errors. But these concepts are what you need to get started.
 

MrSoftware

Joined Oct 29, 2013
2,273
Code:
head->Name[30] = "Vajra";
You cannot do this in C. The statement head->Name[30] references the 31st byte in the character array Name[], which is not your memory since you allocated only 20 bytes. And you cannot fit a whole string into a single byte anyway, plus in C you cannot copy a string this way. Here are 2 ways to do it, an easy way and a correct but painful way:

Code:
   sprintf(head->Name, "Vajra");  // The easy way
  
   head->Name[0] = 'V'; // The painful but technically correct way
   head->Name[1] = 'a';
   head->Name[2] = 'j';
   head->Name[3] = 'r';
   head->Name[4] = 'a';
   head->Name[5] = '\0'; // Terminate the string so any string printing functions stop
 

djsfantasi

Joined Apr 11, 2010
9,237
Save your input in a char array (read from stdIn or somewhere else), like this array:

Char inName[]=“Vajro”;
...
for (Ni=0; inName[Ni]!=0; Ni++ ) Name[Ni]=inName[Ni];​
Name[Ni]=ox00;
is the equivalent code for a strcopy(); A simplification for inputting a name to prevent hard copying the characters for many names.
 
Last edited:

Thread Starter

@vajra

Joined May 2, 2018
154
I have added another node in list that will store the marks of second student student

Code:
#include <stdlib.h>
#include <string.h>

typedef struct List
{
  
    int Marks;
  
    struct List *next;
  
} List;

  int main()
{
   struct List* head = NULL;
   struct List* second = NULL;

   head  = (struct List*) malloc(sizeof(struct List));
   second  = (struct List*) malloc(sizeof(struct List));

   head->Marks = 20;
  
   head->next = second;
  
   second->Marks = 40;
  
   printf(" %d ", head->Marks);
  
   printf(" %d ", second->Marks);
    
   return 0;
}
This is list that store the marks of two student. I can add the another node but How to make list if I don't how many student's are in the class it may be more then 200 so How to make list to store the marks of 200 students
 

djsfantasi

Joined Apr 11, 2010
9,237
Re-read post #11.

In that post, I describe how to add records WITHOUT defining a new variable for each node. I still think you’d benefit from reading about linked lists. Hopefully you’ll learn how to use one variable (of type List) to store many, variable quantity, records!
 

MrSoftware

Joined Oct 29, 2013
2,273
Look up linked list. You only need 2 pointers, one more or less permanent that points to the head of the list, and one temporary that points to the item that you're currently working on. Just keep tacking new nodes onto the end of the list, and make sure the "next" pointer on the last node is null.
 

djsfantasi

Joined Apr 11, 2010
9,237
Look up linked list. You only need 2 pointers, one more or less permanent that points to the head of the list, and one temporary that points to the item that you're currently working on. Just keep tacking new nodes onto the end of the list, and make sure the "next" pointer on the last node is null.
I’m not sure he will listen to you. I mentioned that in post #11. His last post definitely showed he didn't understand what we are saying. Hence, my posting of a couple web resources to explain and demonstrate linked lists.

@vajra,
There is a vocabulary update to understand. A single student record aka structure aka record is represented by a node in a linked list. All records are referenced by pointers. Records are linked by the *next and/or *prev structure fields
 

BobaMosfet

Joined Jul 1, 2009
2,211
Hi @BobTPH

I am creating one node for list

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct List
{
    char Name[20];
    int Marks;
   
    struct List *next;
} List;

  int main()
{
   struct List* head = NULL;
 
   head  = (struct List*) malloc(sizeof(struct List));
 
   head->Marks = 20;
   head->Name[30] = "Vajra";

  while (head != NULL)
  {
     printf(" %d ", head->Marks);
     printf(" %s ", head->Name);    
     head = head ->next;
  }

   return 0;
}
warning: assignment makes integer from pointer without a cast [-Wint-conversion]
head->Name[30] = "Vajra";
^
20 ÿ&╥

Why does code print ÿ&╥ instead of Vajra ?
First, you declared your structure improperly. You cannot use 'List' at the top and the bottom, it can confuse the linker in some compilers. Instead this:

Code:
typedef struct lStruc
   {
   char     name[20];
   int      Marks;
   lStruc   *next;
   }List;
STOP using 'struct this' and 'struct that'! That method only exists because people didn't learn how to make proper type definitions (using typedef), so they have to keep reminding the compiler it's a structure they're dealing with.

Then in main:

Code:
int main()
   {
   List   *head = NULL;

   head = (List*)malloc(sizeof(List));
  
   head->Marks = 20;
   strcpy(head->Name,"Vajra\n");
   head->next = NULL;

   while(!head)
      {
      printf(" %d ",head->Marks);
      printf(" %s ",head->Name);

      head = head->next;
      };

   free(head);               // ALWAYS clean up after yourself.  Release the allocation, and zero the pointer.
   head = NULL;

   return(0);
   }
Look at the above code and pay attention to how I made sure 'next' was also initialized to zero- otherwise your while won't stop. Notice how the syntax is proper for referencing the type 'List' as both a structure and an address.

Hopefully this will help.
 

Thread Starter

@vajra

Joined May 2, 2018
154
I’m not sure he will listen to you. I mentioned that in post #11. His last post definitely showed he didn't understand what we are saying. Hence, my posting of a couple web resources to explain and demonstrate linked lists.
I was not fully ready for linked. my first post was related to structure and I saw linked list in the second post so I thought I should try once then wrote a small program for a list

First, you declared your structure improperly. You cannot use 'List' at the top and the bottom, it can confuse the linker in some compilers. Instead this

Look at the above code and pay attention to how I made sure 'next' was also initialized to zero- otherwise your while won't stop. Notice how the syntax is proper for referencing the type 'List' as both a structure and an address.
I think you have posted code without checking on compiler I have fixed some error in your code

C:
//GCC compiler 
#include<stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct record           
   {
   char     Name[20];
   int      Marks;
   struct record   *next;       // your declaration is wrong 
   }List;
  
int main()
   {
   List   *head = NULL;

   head = (List*)malloc(sizeof(List));
 
   head->Marks = 20;
   strcpy(head->Name,"Vajra\n");
   head->next = NULL;

   while(head)   //  this condition should be head 
      {
      printf(" %d ",head->Marks);
      printf(" %s ",head->Name);

      head = head->next;
      };

   free(head);               // ALWAYS clean up after yourself.  Release the allocation, and zero the pointer.
   head = NULL;

   return(0);
   }
20 Vajra

I do not understand how to extend this program to store marks of students

output of link listed should be following

42 BobTPH
45 BobaMosfet
49 djsfantasi
10 vajra
 
Top