#include "stdafx.h"
#include <stdio.h>
struct s
{
char *st;
struct s *sp;
};
struct s *p1,*p2;
void swap(struct s *p1,struct s *p2);
int main()
{
int i;
struct s *p[3];
static struct s a[]={
{"abc",a+1},{"def",a+2},{"ghi",a}
};
for(i=0;i<3;i++)
{
p[i]=a[i].sp;
}
swap(*p,a);
printf("%s %s %s\n",p[0]->st,(*p)->st,(*p)->sp->st);
return 0;
}
void swap(struct s *p1,struct s *p2)
{
char *temp;
temp = p1->st;
p1->st = p2->st;
p2->st = temp;
}
This program outputs as abc,abc,ghi. My doubt is what does p[0]->st,(*p)->st,(*p)->sp->st outputs.we havent intialised st with abc or ghi.How does it outputs the string?
We havent intialised st with abc or ghi. How does it outputs the
string?
The value of the st member for each structure in the statically allocated array a is actually initialized through an initialization list. Writing
static struct s a[]={
{"abc",a+1},{"def",a+2},{"ghi",a}
};
has the same effective meaning after its execution as writing the following:
static struct s a[3];
a[0].st = "abc";
a[0].sp = a+1;
a[1].st = "def";
a[1].sp = a+2;
a[2].st = "ghi";
a[2].sp = a;
And what's effectively happened after both methods of initialization is you have a statically-allocated circular linked list of struct s, where the data-members of each node in the list (the st member) is pointing to a string literal like "abc", "def", etc. The sp data member is pointing to the next node in the linked list.
I haven't analysed all the statements, but assignment to ->st and ->sp happens here:
static struct s a[]={
{"abc",a+1},{"def",a+2},{"ghi",a}
};
the rest are games with pointers so the output is what you see. So, say:
the a array is created and initialized;
in the for loop the p array is also initialized;
noticing that sp recursively points to struct s instances, p and a have the same structure;
each elements of p is made point to a struct s instance taken from one of the elements of a.
Related
I am creating a simple array of structures in C, but the first structure is always jibberish. How do i fix this?
I have tried to set the first element of the double pointer to struct in many ways but it always fails.
This is my graph.h file:
#ifndef GRAPH_H
#define GRAPH_H
#include "set.h"
typedef struct urlNode * URLList;
typedef struct GraphRep * Graph;
struct urlNode {
int id;
char* URL_NAME;
URLList next; // link to next node
};
struct GraphRep {
int nV;
URLList * collections;
};
Graph newGraph(Set s);
int nameToId(Graph g, char *name);
void showGraph(Graph g);
#endif
And my newGraph(Set s) function looks like this:
Graph newGraph(Set s){
int size = nElems(s);
Graph new_graph = malloc(sizeof(struct GraphRep));
if (new_graph == NULL) {
printf("ERROR: COULDNT ALLOCATE GRAPH\n");
}
new_graph->nV = size;
char *name = getNextVal(s);
// THIS IS THE NODE TO BE ADDED TO THE GRAPH
URLList list_to_add = malloc(sizeof(struct urlNode));
list_to_add->URL_NAME = strdup(name);
list_to_add->id = 0;
list_to_add->next = NULL;
// HERE I ADD THE NODE TO THE GRAPH.
new_graph->collections[0] = list_to_add;
// PRINT OUT THE VALUES OF THE NEWLY ADDED NODE TO MAKE SURE IT WORKS
// THE URL_NAME IS PRINTED OUT FINE
// BUT THE ID IS JIBBERISH.
printf("%s\n", new_graph->collections[0]->URL_NAME);
printf("%d\n", new_graph->collections[0]->id);
if(new_graph->collections[0]->next != NULL) {
printf("%s\n", new_graph->collections[0]->next->URL_NAME);
printf("%d\n", new_graph->collections[0]->next->id);
}
printf("\n");
return new_graph;
}
I expect new_graph->collections[0]->id to be 0 but it keeps on giving me random ints.
Also even if the next for the newly declared pointer to struct is NULL, it still gives me a jibberish next value too.
Any help would be appreciated, thanks!
The data member collections of the object *new_graph is not initialized.
There is initialized only this data member
new_graph->nV = size;
So this statement
new_graph->collections[0] = list_to_add;
results in undefined behavior.
If you need an array of pointers of the type URLList you have to allocate the memory and its address assign to the pointer collections.
For example
new_graph->collections = malloc( new_graph->nV * sizeof( URLList ) );
And after that this statement
new_graph->collections[0] = list_to_add;
could be valid.
(I suppose that the data member nV corresponds to the number of elements in the dynamically allocated array though it may not be truth)
Pay attention to that as the string pointed to by the pointer name is not changed in the function then it is better to declare it like
const char *name = getNextVal(s);
Generally, I know that a pointer stores the memory address of another value located in computer memory, for example:
int firstvalue= 5
int * p1;
p1 = &firstvalue; // p1 = address of firstvalue
What happens if we define an operation like the following in a linked list? Does *current=*list means that the value pointed to by current equals to the value pointed to by list? And what does it mean if we define ecur=current?
int function(struct list_t **list){
struct list_t *ecur=NULL;
struct list_t *current=*list;
ecur=current;
}
Update:
What does it do *list=remove(*list, param1, param2)? And why is that?
remove is a function that returns a modified list of list.
Update 2:
Why do we need to define a pointer to pointer in order to modify the list? Is *list a pointer to pointer?
The variable list is a pointer to a pointer to a struct list_t. If we (just as an example) assume that the struct is placed at address 2000 and that the unnamed pointer is at address 1000 it will look like this:
Then you have the initialization that adds two new variables. Both as pointer to a struct list_t.
struct list_t *ecur=NULL;
struct list_t *current=*list;
So the picture now becomes:
Notice that current got the same value as the "some-pointer" in the middle because it is *list that was assigned to current.
Then you have the assignment:
ecur=current;
which means that ecur gets the same value as current and gives the picture:
Update: What does it do *list=remove(*list, param1, param2) ?
It changes the value of the "some-pointer" in the middle of the picture. This is for instance needed if the remove function removes the first element in a linked list.
Why do we need to define a pointer to pointer in order to modify the list? Is *list a pointer to pointer?
Remember that C passes all function arguments by value - the formal argument in the function definition is a different object in memory from the actual argument in the function call. For example:
void swap( int a, int b )
{
int tmp = a;
a = b;
b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( x, y );
}
a is a different object in memory than x, and b is a different object in memory than y, so swapping a and b has no effect on x and y. In order to swap the values of x and y, you must pass pointers to them:
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( &x, &y );
}
The expression *a is the same as x, so writing to *a is the same as writing to x. Same for *b and y.
So, in order for a function to write to a parameter, you must pass a pointer to that parameter:
void foo ( T *arg )
{
*arg = new_value(); // writes a new value to the thing arg points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
This is true for any non-array type T. Let's replace T with a pointer type P *:
void foo( P **arg )
{
*arg = new_value(); // write a new *pointer* value to the thing arg points to
}
void bar( void )
{
P *var;
foo( &var ); // write a new pointer value to var
}
The semantics are exactly the same - all that's changed is the type.
If a function has the potential to modify a list * object (say pointing it at a new list head), then you must pass a pointer to that list * object:
void add_node( struct list_t **list, struct list_t *node )
{
if ( !*list || (node->value < (*list)->value) ) // make node new head of list
*list = node;
else
// add node somewhere else in the list
}
int main( void )
{
struct list_t *list = NULL;
...
struct list_t *node = newNode( value );
add_node( &list, node );
...
}
TYPE *p = ptype /*variable of type: TYPE * */;
is not an assignment. It's an initialization, which for an auto-matic (=on-the-stack) p can be rewritten as:
TYPE *p;
p = ptype;
(not TYPE *p; *p=ptype; /*would be a type error*/)
In terms of your example:
struct list_t *current=*list;
sets where current will point to (the same place as what *list points to (*list is also a pointer because list is a doubly-indirect pointer)) without doing anything whatsoever with what current will point at (*current) after the initialization.
All of this is just conceptual, though. Your function doesn't have any externally visible effects so an optimizing compiler should completely delete its body.
I had a similar knot in my head with this post. I'd like to rearrange your function a bit, so it's easier to understand what's going on:
int function(struct list_t **list)
{
struct list_t *current = *list;
struct list_t *ecur = current;
}
If we call this function with an element foo we essentially get this:
struct list_t foo = { .data = "foo" };
struct list_t *bar = &foo;
struct list_t **list = &bar;
struct list_t *current = *list;
struct list_t *ecur = current;
We have five declarations and five assignments. For better readability, I'll write everything down without declarations:
foo = { .data = "foo" };
bar = &foo;
list = &bar;
current = *list;
ecur = current;
Now, let's walk through it:
foo is a struct. It contains the above data-field.
bar is a pointer to struct. It contains the address of foo
list is a pointer to a pointer to struct. It contains the address of bar
current is a pointer to struct. It contains the contents of the contents of list, which is the address of foo
ecur is a pointer to struct. It's identical to current and contains the address bar
In the end we can simplify the whole example to this:
struct list_t foo = { .data = "foo" };
struct list_t *ecur = &foo;
What does it all mean?
list: Because list is a pointer to a pointer you are able to modify bar to point to something completely different, by de-referencing it (*list = ...)
current/ecur: that's what bar originally pointed too. By de-referencing you could change the data-field itself ((*ecur).data = "banana" or better ecur->data)
I hope I could clarify things and didn't make it worse ;)
Why do we need to define a pointer to pointer in order to modify the
list?
Let me add a complete program, albeit short, to illustrate it better. It defines a simply linked list and builds it while keeping it ordered. Yes, I know it would be easier to simply call qsort(), but I want to demonstrate how adding one level of indirection —the pointer to pointer— allows to insert elements smoothly, without testing for special cases.
// C pointer exercise: sort arguments
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
struct list
{
char *arg;
struct list *next;
};
int main(int argc, char *argv[])
{
// pointer to base, running pointer and pointer to pointer
struct list *base = NULL, *p, **pp;
for (int i = 1; i < argc; ++i)
{
struct list *new_entry = malloc(sizeof(struct list));
if (new_entry)
{
new_entry->arg = argv[i];
// find where to insert new entry
for (pp = &base; *pp; pp = &(*pp)->next)
if (strcasecmp(new_entry->arg, (*pp)->arg) < 0)
break;
// insertion in a simply linked list
new_entry->next = *pp;
*pp = new_entry;
}
}
// display and cleanup
for (p = base; p;)
{
struct list * tmp = p->next;
puts(p->arg);
free(p);
p = tmp;
}
return 0;
}
I have a function called SemCreate that takes a name an int and a pointer as parameters. I want the pointer to point to a new struct and I want to return an int, 0 if it went okay.
int P1_SemCreate(char *name, unsigned int value, P1_Semaphore *sem){
USLOSS_Console("Create a semaphore\n");
if(!verifyKernel()) {
//USLOSS_Console("ERROR: Not currently in Kernel mode\n");
USLOSS_Halt(1);
}
if(numSems>= P1_MAXSEM){
//USLOSS_Console("ERROR: MAX semaphore already exist\n");
return -2;
}
if(name == NULL){
return -3;
}
interruptsOff();
int i;
for (i = 0; i < P1_MAXSEM; i++) {
if (semTable[i].inUse == 0) {
semTable[i].value = value;
semTable[i].list = NULL;
semTable[i].name = malloc(sizeof(char));
strcpy(semTable[i].name, name);
semTable[i].inUse = 1;
semaphore *temp = NULL;
temp = malloc(sizeof(semaphore));
temp->value = value;
temp->list = NULL;
temp->name = malloc(sizeof(char));
strcpy(temp->name, name);
*sem = temp;
break;
}
}
numSems++;
interruptsOn();
return 0;
}
Right now the pointer is fine within the function but once I return the pointer is null
EDIT: The array semTable is an array of semaphores
typedef struct semaphore{
int value;
char * name;
struct node *list;
int checkPoint;
int inUse;
}semaphore;
typedef struct PCB {
USLOSS_Context context;
int (*startFunc)(void *); /* Starting function */
void *startArg; /* Arg to starting function */
int pid;
int status;
int killedStatus;
int state;
int priority;
char name[50];
int parentPID;
int numOfChild;
int blockFlag;
struct sempahore *blockSem;
char *stack;
struct node *children;
struct node *zombiList;
int cpuTime;
int startTime;
struct semaphore *childSem;
} PCB;
typedef struct node {
PCB *pcb;
struct node *next;
} Node;
Your question is not perfectly clear as to what you are trying to do. So, this answer addresses the following general topics in hopes they will assist:
1) Passing the address of a struct via a function, changing the values of the struct members, and accessing changed values in calling function. (It is not the same as the one you show, but illustrates what you want to do.)
2) Creating instances and pointers to instances of a struct, then initializing.
3) Contains link to tutorial on self referencing structs. (as you are doing in your posted code)
typedef struct {//struct definition created in global space, typedef'ed
char line[80]; //to read in the line
int slot;
char type[20]; //long enough for any types listed
int position;
}SLOT;
int modifyStruct(SLOT *slot);//prototype of demonstration function
int main(void)
{
SLOT s;//create instance of SLOT local to main
int ret = modifyStruct(&s);pass address of SLOT instance to change member values
printf("Line: %s\n", s.line);//show changed values
printf("Slot: %d\n", s.slot);
printf("type: %s\n", s.type);
printf("position: %s\n", s.position);
return 0;
}
int modifyStruct(SLOT *slot)
{
strcpy(slot->line, "lineA");
slot->slot = 2;
strcpy(slot->type, "large");
slot->position = 20;
return 0;
}
EDIT - To address question in comment asking how to set a struct pointer to point to a struct.
First, it appears from viewing the code you have posted, that you are using self referencing structs. (i.e. a struct that contains a member that is a pointer instance to itself) Here is a link to a good tutorial dealing with Linked Lists in C, which use self referencing structs.
Regarding you comment: _I guess I should have made it more clear. P1_Semaphore is different to semaphore. I need P1_semaphore to point to the semaphore_.:
If P1_Semaphore is different than semaphore, then one should not be set to point to the address of the other. And your compiler will not let you do that anyway.
As I stated in the comments, a struct pointer should only point to a place in memory that contains an instance of that struct. For example consider the two structs A & B:
typedef struct {
int iNum;
float fNum;
char cStr[80];
}A;
A a, *pA; //create an instance, and pointer to an instance of A
typedef struct {
int iNum1;
int iNum2;
int iNum3;
}B;
B b, *pB; //create an instance, and pointer to an instance of B
A & B are obviously different, and will occupy a different size and shape in memory, so if the pointer to B, *pB was set to point to anything but B, it would be incorrect. It needs to point to B
Correct:
pA = &a //set pointer to A equal to the address of A
pB = &b //set pointer to B equal to the address of B
Incorrect:
pA = &b //set pointer to A equal to the address of B
pB = &a //set pointer to B equal to the address of A
(typical compiler error - Operands of = have types pointer to B and pointer to A)
In C/C++, all parameters are passed by value, not by reference. To get the struct pointer in parameter, you need to use pointer to pointer as the parameter. Like this:
int P1_SemCreate(char *name, unsigned int value, P1_Semaphore **sem){
...
*sem = temp;
...
}
I am having a problem with pointers.
this is an example of what I want
struct Book
{
char name[10];
int price;
}
int main()
{
struct Book b[10]; //Array of structure variables
struct Book* p; //Pointer of Structure type
p = &b; --- HERE is the ERROR
}
This is the error part
p = &b;
b is an array, which can itself decay into a pointer variable. By writing &b, you actually take the address of that pointer and then you end up with pointer to a pointer. It is enough to just write p = b.
Try this. I have not checked but this should work.
p = b;
now if you want to iterate you array of structure then do this
// Example program
#include <stdio.h>
struct Book
{
char name[10];
int price;
};
int main()
{
struct Book b[10]; //Array of structure variables
struct Book* p; //Pointer of Structure type
p = b;
int i = 0;
for(i = 0 ; i<10; i++)
{
printf("Price : %d\n", (p+i)->price);
}
}
b itself is a pointer. Here you can think of arrays as of pointers. So use p=b instead of p=&b
If I have several linked structures in C like:
struct structA {
int a;
int b;
struct structA *next;
}
struct structB {
char a;
int b;
struct structB *next;
}
and I dynamically allocate memory like this:
struct structA *mystructA = (struct structA*) malloc(sizeof(struct structA));
mystructA->next = (struct structA*) malloc(sizeof(struct structA));
struct structB *mystructB = (struct structB*) malloc(sizeof(struct structB));
mystructB->next = (struct structB*) malloc(sizeof(struct structB));
do I always have to free it for each struct type like this:
struct structA *p, *pNext;
for (p = mystructA; p != NULL; p = pNext) {
pNext = p->next;
free(p);
}
struct structB *p, *pNext;
for (p = mystructB; p != NULL; p = pNext) {
pNext = p->next;
free(p);
}
or is there any generic solution? I assume there is no other solution because the free() procedure must know how many bytes have to be freed. But maybe I'm wrong and someone can teach me better.
The standard way is to make the "list part" the first element of the structure, and let each derived struct share this same prefix. Since the first element is guaranteed to be placed at offset zero this wil work.
Example snippet:
#include <stdlib.h>
#include <string.h>
struct list {
struct list *next;
};
struct structA {
struct list list;
int a;
int b;
};
struct structB {
struct list list;
char a;
int b;
};
void *create_any(size_t size)
{
struct list *this;
this = malloc (size);
if (!this) return this;
memset(this, 0, size);
this->next = NULL;
return this;
}
void free_all_any(struct list **lp) {
struct list *tmp;
while ((tmp = *lp)) { *lp = tmp->next; free(tmp); }
}
#define CREATE_A() create_any(sizeof(struct structA))
#define CREATE_B() create_any(sizeof(struct structB))
#define FREE_A(pp) free_any((struct list **) pp)
#define FREE_B(pp) free_any((struct list **) pp)
int main(void)
{
struct structA *ap;
struct structB *bp;
ap = CREATE_A ();
bp = CREATE_B ();
// some code here ...
FREE_A( &ap);
FREE_B( &bp);
return 0;
}
This is more or less the method used in the linux kernel, but a lot more preprocessor magic is used there. (and there is no malloc there, obviously)
Since free() accepts pointers to void * and structA and structB both have the same size, you can pass both pointer types.
This is, however, not optimal in terms of elegance. You should think about the following questions:
Why do you have two different structs with the same members?
Why do you not have a generic list item type, such as the following:
struct list_node {
void *data;
struct list_node *next;
}
Actually, this is a very interesting question. The part is true that you have to free() each struct type individually, as they have been malloc()-ed individually, and each memory block has been allocated specifically for that type.Also, on some systems char and int have different storage sizes, but you can try a solution like Phillip provided. For more info, read about the doom memory engine. On a side note, please don't cast malloc() in C. The funny thing is that once the program is terminated, the operating system will reclaim the memory, so if you only deallocate the structures near the end of the program, when you don't need them anymore, it may not be necessary to free() them