Difference Between *list and **list - c

If I have a struct:
typedef struct A
{
char c[100];
}A;
Then I create a
sizeOfA = 5000;
A *list = (A*) malloc(sizeOfA * sizeof(A));
Is list[i] a pointer to a struct?
Or if I want a pointer to the struct, should I do
A **list = (A**) malloc (sizeOfA * sizeof(A*);
[EDIT]
Now let's say I created the list using A *list (which I did already). How would I create 5000 pointers and make them point to the elements on the list?
p0 -> list[0]
p1 -> list[1]
..
..
p[n] -> list[n]
After going back and forth a few times I noticed that for sorting the pointers help a lot.
To be fair I will post the edit above as a separate question.

After this statement:
A *list = (A*) malloc(sizeOfA * sizeof(A));
list is a pointer to the starting location of a memory block that can hold sizeOfA elements of type struct A. Thus, *list is of type struct A, and similarly, list[i] is of type struct A, not pointer to struct A (that would be list+i).
If you want list[i] to be a pointer to struct A, then your second piece of code would be the correct one, since you're allocating a memory location with enough space to hold sizeOfA pointers to struct A. Note that you are only allocating space to hold pointers, not actual struct A instances. Attempting to read list[i]->c will result in undefined behavior.

A *list = (A*) malloc(sizeOfA * sizeof(A));
Is list[i] a pointer to a struct?
No -- list is a pointer to an address in the heap, which is the start of a memory chunk that has size sizeOfA * sizeof(A). list[i] is the same thing as *(list + i), which is a dereference that will give you an actual A.
However..
A **list = (A**) malloc (sizeOfA * sizeof(A*);
Is list[i] a pointer to a struct?
Yup.

Related

What is the size of a structure pointer in C?

If the size of a structure pointer is 4 or say 8 bytes, how can it properly allocate the required memory for its data members in Dynamic Memory Allocation. This is my code:
#include<stdio.h>
typedef struct node{
char a[10];
char b[10];
char c[10];
int f;
struct node* next;
}node;
int main()
{
node* temp;
int d= sizeof(node *);
printf("Size of structure pointer = %d",d);
temp= (node*)malloc(sizeof(node*));
int c = sizeof(temp);
printf("Size of Temp = %d\n",c);
}
```````````````````
/*
Here both Temp and node* is having a size of 8 bytes.
But the size of the structure 'node' is 38 bytes(total size of the members).
So how can the pointer Temp allocate that much memory if its size is just 8 bytes ?
*/
Because you don't store data in pointers. Pointers point at data allocated elsewhere, hence the name "pointer". sizeof(node*) is wrong and the size of the pointer itself is irrelevant.
You should do
temp = malloc(sizeof *temp); // equivalent of sizeof(Node)
...
free(temp);
This is the pointer to the node struct, you don't need to allocate space for it. It can point to the node structure.
struct node *node_ptr;
If you want to store node structure at some pointer, you need to allocate space for the node structure NOT THE POINTER
node *node_data = malloc(sizeof(struct node));
You don't need to cast the result from the malloc, it is bad { see casting for malloc }
Pointer is just the pointer. It you are a tourist guide in the war museum and use the pointer to show the tank - what is the weight of the pointer in your hand? The weight of the wooden stick or the weight of the tank?
First lets understand about malloc:
Malloc is a function which allocates memory in a HEAP part of RAM. If we define a variable, usually it gets allocated in STACK part of RAM.
temp = (int*)malloc(n*sizeof(int));
this code allocates a memory in HEAP.
Now lets understand about ponters:
consider the following code.
int a;
int *p;
p=&a;
in the about line of code the pointer 'p' is storing the address of the variable 'a'.
Depending on the word length of your system(32bit or 64bit), the size of the pointer variable 'p' changes. It can be 2bytes or 4bytes or 8bytes. 8bytes is because in 64bit machine, "long int" can takes 8bytes.
Now lets understand about both pointers with structure:
struct value{
int a;
int b;
char c;
};
Since above code is a definition of structure, memory won't get allocated.
struct value s;
now the memory gets allocated in Stack.
struct value *s;
s = (struct value*)malloc(sizeof(struct value));
here the memory gets allocated in Heap.
Even though 's' is structure pointer it still stores the address of the whole structure 'value', it's size will be 4/8. It points to whole structure not the particular member of structure.
The general structure 's' will have the data part of all its members. So the size will be 5 or 9 depending of the machine and the padding.
struct s{
int a; /* 4 bytes */
char b; /* 1 byte */
/* 1 padding byte */
short c; /* 2 bytes */
};
Refer Data Structure Padding

Declaring a pointer to struct creates a struct?

It seems to me like struct new_element *element = malloc(sizeof(*element)) creates a structure of type element, whereas I thought it would only create a pointer to it. The following code proves to me I'm wrong:
struct new_element
{
int i;
struct new_element *next;
};
int main(void)
{
struct new_element *element = malloc(sizeof(*element));
element->i = 5;
element->next = NULL;
printf("i = %d, next = %p\n", element->i, element->next);
}
Output:
i = 5, next = (nil);
element->i was given the value 5 and element->next was given the value NULL. Doesn't that mean that element points to a structure, which would mean that there is a structure that was created? I thought that malloc would only give a pointer the size needed in memory.
The variable element is a pointer. When you define it, that sets aside space for the pointer.
If you just did this:
struct new_element *element;
You've created a pointer. It just doesn't point anywhere.
When you then call malloc(sizeof(*element)), that sets aside space big enough for what element points to, i.e. an instance of struct new_element. You then point the variable element to this section of memory.
This syntax:
element->i = 5;
Is the same as:
(*element).i = 5;
It dereferences the pointer element, giving you a struct new_element, then you access the member i.
If you did this, as you suggested in the comments:
struct new_element *element = malloc(sizeof(element));
You're not allocating the proper amount of space. You're setting aside enough space for a struct new_element * instead of a struct new_element. If the struct is larger than a pointer to it (likely in this case, since it contains a pointer to its own type), then you end of writing past the end of the allocated memory when modifying one of the members. This invokes undefined behavior.

Compiler error (lvalue required as left operand of assignment) when using malloc

I got 2 structs,a pointer to each struct and a void **stack which points to the pointers of the structs.
my problem is at the line
(*ptr2+*a)=(struct student *)malloc(sizeof(struct student));
*a is a variable that increases by 1 everytime a stud registration happens so i don't allocate memory for the same address over and over again
since i send the address of stud(&stud) at the menu function and then at the input function
*ptr2==stud
thus
stud[*a]== *(stud+*a)== *(*ptr2+*a)
why is (*ptr2+*a) on the left side of malloc wrong?
part of the code
struct student
{
char flag;
char surname[256];
int semester;
};
main()
{
...
struct student *stud;
menu(stack,stackcopy,reversedstack,&prof,&stud,stacksize,&head);
...
}
void menu(void **stack,void **stackcopy,void **reversed,struct professor **ptr1,struct student **ptr2,int size,int *head)
{
...
input(stack,ptr1,ptr2,size,head,&a,&b);
...
}
int input(void **stack,struct professor **ptr1,struct student **ptr2,int size,int *head,int *a,int *b)
{
...
done=Push(stack,head,(*(int *)ptr2+*a),size);
(*ptr2+*a)=(struct student *)malloc(sizeof(struct student));
stud_input(ptr2,a);
...
}
It's wrong because you need (roughly) a variable on the left side of the assignment, not a value. You can't write 1 = 2;, but you can write int a; a = 1;. By the same logic, you can't write &a = (void*)0;.
Dereferencing a pointer gives you a variable, so you can write struct student *z = &a; *z = b;.
If you want to write stud[*a] = malloc(...);, but you don't have stud, only ptr2, for which *ptr2 == stud holds, the correct way is, obviously,
(*ptr2)[*a] = malloc(...);
And (*ptr2)[*a] == *(*ptr2 + *a), so this would work as well:
*(*ptr2+*a) = malloc(sizeof(struct student));
my problem is at the line with
(*ptr2+*a)=(struct student *)malloc(sizeof(struct student));
Do I cast the result of malloc?
I have edited this answer because I was completely wrong on the first try. In my head, there was one level of indirection more than you actually have.
Suppose you want to malloc() a number of entries and assign it to stud, i. e. write it to where stud actually sits.
If you were up to do it in main(), you'd do
struct student *stud = malloc(n * sizeof(*stud));
resp.
struct student *stud;
stud = malloc(n * sizeof(*stud));
if you want to have space for n entries.
If you want to do the same in the called function, then you replace stud with *ptr2:
*ptr2 = malloc(n * sizeof(*stud));
It seems you want to allocate only one entry here. Then you just do
*ptr2 = malloc(sizeof(*stud));
Be aware that you have only one pointer which you can use to access either one entry (as you seem to want it), or an array of entries allocated appropriately.
While it is true that
stud[*a]== *(stud+*a)== *(*ptr2+*a)
you are only allowed to access as many entries as you have allocated. Especially, if you have allocated only as much space as needed one entry, you are only allowed to use
stud[0] == *stud
both of which is a struct student and cannot be assigned the result of a malloc() call.
If you do an allocation of, e. g.,
malloc(10 * sizeof(*stud))
and assign that to stud or to *ptr, you can access more.
OTOH, (*ptr2+*a) == (stud + *a) == &stud[*a] == &(*ptr2)[*a]. But this is nothing you can assign to, as the compiler tells you, this is not an lvalue. And even if it was not an lvalue, you were not allowed to access it this way: while &stud[0] is exactly stud, &stud[1] points to the element after the one stud points to.
And as long as you haven't allocated enough for that to exist, this access is invalid for reading, and even so for writing: you cannot change the address of the 2nd element, as it always is the address of the first one plus sizeof(*stud) bytes.
I am really not completely clear about what you are up to; I suppose you want to allocate an array and to that in the wrong way.

How to assign value to a memory address calculated by pointer arithmetic?

I need to create a completely generic linked list that can contain any type of data specified by an enum...
A node of the list has the structure:
__________________
|_____|_____|_____|
The first field is of sizeof(nodeType) bytes containing the type of information stored. The next field has an address that contains address of the information variable. The next field has the address of the next node which can be a simple node or yet another linked list..
Basically, I have a nodeType enum as:
typedef enum{
STRING, INT, NIL, LIST
} nodType;
I have allocated memory to a node pointer like this:
nodeType* node = malloc(sizeof(nodeType) + 2*sizeof(char*));
The first sizeof(nodeType) bytes contain the type of inofrmation stored. I assigned it the value STRING by the expression:
*node = STRING;
Now, I want the next sizeof(char*) bytes store the address of a char* pointer. (All pointers are of the same size on a machine?(yes, acc to me)).. So, I assign a value to it like:
char* str = strdup("Hello");
(char**)(char*(node) + sizeof(nodeType)) = &str;
But GCC flags an error as the LHS of assignment operator is not an lvalue..
I need to assign value to that address in order to go ahead to build that list.
Is there some elegant way of doing that in c apart from using a struct??
You forgot to dereference:
*(char***)((char*)node + sizeof(nodeType)) = &str;
The result of a dereference operation is always an lvalue. In general, if you want to treat a memory lo­ca­tion p as if it pointed to a variable of type T, you need to cast it to a T * and dereference:
*(T*)(p) = my_t_value;
This applies to your situation for T = char ** and p = (char *) node + sizeof(nodeType).
But this is just terrible design. No sane could should contain ***. And moreover, you're potentially vio­la­ting alignment constraints by assuming that all your elements follow contiguously in memory. A much sim­pler way would be something like this:
struct Node
{
struct Node * next;
nodType type;
void * data;
};
Usage:
struct Node * p = malloc(sizeof *p);
p->next = NULL;
p->type = STRING;
p->data = str;
Note that I chose to store a string directly as a char *, and not as a pointer to a char *. The uni­fy­ing theme should be that the list node owns p->data and should say free(p->data); upon node re­moval unconditionally.

Pointer to an array of pointers to Linked lists

I have been at this problem for the last 6 hours and have been hitting google like mad to no avail.
Right I need a pointer to an array. This array contains pointers to Linked lists. Im going to have to malloc it since I dont know the array size until runtime.
LList **array
This was my first thought but this just gives me a pointer to an array of LList. Or atleast that is my understanding. Can someone give me a hand?
EDIT: Some info on how it would be used: I am implementing a very basic hash table. There is a structure that contains a pointer to an array of pointers to linked lists.
It needs to be a pointer to the array so that when I resize the table. I can just change the pointer to point to the larger table.
It sounds like you're on the right track.
LList **array;
array = malloc(num_ptrs * sizeof(LList*));
array is now an array of pointers to LList, and elements such as array[3] will be a pointer to a LList.
Arrays and pointers are very similar in C (but not identical!), as shown by the classic example: *(array + 2) is mostly equivalent to array[2].
Edit:
When you need to resize the table, you'll just need to realloc the additional space:
LList **new_array;
new_array = realloc(old_array, new_size * sizeof(LList*));
new_array and old_array may or may not be the same pointer afterwards, but either way new_array is guaranteed to be a pointer to enough space to hold the new array (or NULL if the memory couldn't be allocated)
2nd Edit:
As user411313 alluded, if you want the actual pointer to the array, you'll need to take the address of the array:
LList ***p_array;
p_array = &array;
A pointer to an object, is basically the same as a pointer to an array.
int * blah; // an int pointer. It could point to an array of ints, or a single int.
int ** blah; // a pointer to an int pointer. It could point to something that points to an int, or it could be pointing to an array of pointers to single ints, or it could be a pointer that points to an array of ints.
It all depends on how you use it.
A pointer to a pointer can also be an array of pointers.
int nLists; /* number of lists*/
LList **array;
array = (LList **)malloc(nLists * sizeof(LList *));
will make array be an array of pointers to LList. Then array[i] will give you the pointer to the i-th linked list in the array.
if you have to write your own linked list, you can do this.
typedef struct LLNode {
LLNode* next;
int data;
} LLNode;
LLNode* linkedList = null; // a linked list
LLNode** linkedListArray = (LLNode**) malloc( arraySize* sizeof(LLNode*) );
LLNode*** pointerToLListArray = &linkedListArray;
with a linked list library:
LList* linkedListArray = (LList*) malloc( arraySize* sizeof(LList) );
LList** pointerToLListArray = &linkedListArray;
typedef struct LList LList;
struct LList {
int value;
LList *next; };
LList *(*p)[3]; /* pointer to an array of 3 pointers to LList */
LList ll1 = {11};
LList ll2 = {22};
LList ll3 = {33};
size_t sizeofarray = sizeof*p/sizeof**p; /* calc arraysize at runtime here */
p = malloc( sizeofarray * sizeof**p ); /* allocate space for each LList-pointer in array */
(*p)[0] = &ll1;
(*p)[1] = &ll2;
(*p)[2] = &ll3;
/* test output here: */
printf("\n%d\n%d\n%d", ((*p)[0])->value,((*p)[1])->value,((*p)[2])->value);
free(p);

Resources