How does struct Node *ptr = malloc(sizeof(*ptr)) work? - c

I'm a C beginner, and I came across this code while trying to implement a linked list.
struct Node *ptr = malloc(sizeof(*ptr));
The Node struct looks like this:
struct Node {
int data;
struct Node *next;
};
I'm trying to understand the first line. It seems as if malloc(sizeof(*ptr)) already knows the contents of ptr. What exactly is happening on the left side and is it happening before malloc is called?

It seems as if malloc(sizeof(*ptr)) already knows the contents of ptr.
Actually, it doesn't. The sizeof operator doesn't actually evaluate its operand (unless it's a variable length array), it just looks at its type. This means that ptr isn't actually dereferenced and is therefore a safe operation.

Only use paranthesis with sizeof if there's a type you'd like to know the size of. If you have an expression, like *ptr, it's enough to write:
struct Node *ptr = malloc(sizeof *ptr); // <- no parenthesis
The expression *ptr dereferences the pointer so it becomes a struct Node and that's what the sizeof is returning the size for.
sizeofexpression - Returns the size, in bytes, of the object representation of the type of expression. No implicit conversions are applied to expression.
It's the same size you get if you do:
struct Node *ptr = malloc(sizeof(struct Node)); // <- parenthesis needed
but the first alternative is often preferable for clarity.

You need to allocate a memory for an object of the type struct Node declared like
struct Node {
int data;
struct Node *next;
};
So in the call of malloc you need to specify the size of the memory to be allocated for an object of this type. The function malloc returns a pointer to the allocated memory.
So you can write
struct Node *ptr = malloc( sizeof( struct Node ) );
On the other hand, the expression *ptr has the type struct Node. That is the declared pointer ptr has the pointer type struct Node * and dereferencing such a pointer like *ptr yields an expression of the type struct Node.
So you may rewrite the above record also like
struct Node *ptr = malloc(sizeof(*ptr));
because in this case sizeof( struct Node ) is equivalent to sizeof( *ptr ).
That is the compiler needs to know the type of the operand of the operator sizeof that to determine the size of an object of that type.

Related

What does the following code do in regards to structure pointers?

struct node *link = (struct node*) malloc(sizeof(struct node));
The above code is part of a larger program that creates a linked list. I already have and understand the code that leads up to this which creates the structure "node". I just am unsure what the code I provided does in regards to that structure.
The above code simply allocates memory of dimension "struct node", then cast it to the same type and assign the returned pointer to a variable called link.
Well, let's go through it piece by piece....
First, this tells that you are after a pointer to a struct of type node not a struct node but a pointer that points to a memory location holding a struct node
struct node *link = ...
then, let's have a look at the signature of the malloc() function.
void *malloc(size_t size);
It tells us that the return type is void *, which , in C, can be casted to any other type and generally used to provide a universal interface to the caller (similar to but not same as templates in C++ or other languages).
With the below cast, we are casting void *, the return type of malloc() to a pointer to a struct of type node, i.e. struct node*
(struct node*) malloc(...);
Looking at the argument passed to the malloc() function, which gives the size of an expression measured in char-sized storage units (sizeof(char) is guaranteed to be 1)
...sizeof(struct node)...
you are asking your compiler to return you the size of your struct node (this, of course, depends on the members of your struct).
Putting it all together...
struct node *link = (struct node*) malloc(sizeof(struct node));
allocate memory as big as a struct of type node can fit and return me a pointer to the start of this memory chunk. At the same time, mark this chunk of memory so that you (the compiler) will know that this area is reserved for a struct of type node
Edit : In C, you do not need to cast the type of the pointer returned by malloc() to another pointer type. In your case, the returned void * pointer from malloc() is automatically promoted to the appropriate pointer type, i.e. struct node*.

get the value from pointer to pointer in struct

I have a struct:
struct structname
{
structname** link;
int total;
}
I want to link structname1 to structname2. What I did was:
int *ptr = &structname2;
structname1 -> link = &ptr;
Then I tried to access the link for structname1 which is structname2:
structname *test = structname1 -> link;
Is this the correct way to do it? When I tried to print out, some unknown symbols printed. Can someone help me with this? Thanks.
You have to do in the below way.
struct structname structname1, structname2; //define two structures structname1 and structname2 of type structname.
struct structname * ptr; // ptr is a pointer to struct of type structname.
struct structname ** ptr2 // ptr2 is a double pointer to struct of type structname.
ptr = &structname2; // ptr points to structname2
ptr2 = &ptr; // ptr2 points to ptr and ptr points to structname2;
structname1.link = ptr2; // now link is a double pointer to structname2.
Let me correct if i'm wrong or missing
You have a couple of things wrong in your code. First, you got the type for ptr wrong: it should be struct structname ** instead of int *.
But if you're trying to do a linked list, you don't need the double indirection level at all. This is most likely what you want:
struct structname
{
struct structname *link;
int total;
}
With that, linking structname1 with structname2 is then as simple as (assuming structname1 and structname2 are of type struct structname):
struct structname *ptr = &structname2;
structname1.link = ptr;
If structname1 and structname2 are of type struct structname *, then you need this instead:
struct structname *ptr = structname2;
structname1->link = ptr;
You could also drop the intermediate variable ptr, it's not of much use here.
struct node {
struct node *next;
int cargo;
}
struct node *current, *last, *next;
unsigned char i;
current = (struct node*)(calloc(sizeof(struct node)));
for (last = current, unsigned char i = 5; i--;) {
next = (struct node*)(calloc(sizeof(struct node)));
next->cargo = i;
last->next = next;
}
The above code is a very easy linked list. Note that I changed a couple of things compared to your code. I create the objects using calloc, that means that the objects will be allocated on the heap instead of the stack. This also doesn't require you to have explicit names for every element, a.k.a. node in the linked list. It also means it won't be destroyed when you leve the scope of the names. Of course you will need to free all the nodes later, when you don't need the list anymore.
Then you don't need a pointer to a pointer in the node, a simple pointer is sufficient. In your main program you should also use an appropriate pointer. Even though, all pointers are the same size and can be cast into each other, you should - whenever possible - usde the right type.
Here I create another 5 nodes in a loop to demonstrate how 'flexible this approach is'.
If you want to do a circular linked list, that is quite easy as well. Simply append these line:
next->next = current;

placement of unary operator when using pointers in C

I am trying to learn about pointers in C, and don't understand why the unary * operator was appended to the end of the word "node" in the following code snippet:
struct node* CopyList(struct node* head) {
/* code here */
}
From my understanding of pointers, one can create a pointer with a statement like
int *pointerName;
and assign a "pointee" to it with a statement like
pointerName = malloc(sizeof(int));
and then dereference the pointer with a statement like
*pointerName = 4;
which will store the integer value 4 in the 4 bytes of memory (pointee location) which is "pointed to" by the pointerName pointer.
WITH THAT BEING SAID, what does it mean when the * is appended to the end of a word, as it is with
struct node*
???
Thanks in advance!
http://cslibrary.stanford.edu/103/
The location of the * ignores the whitespace between the base type and the variable name. That is:
int* foo; // foo is pointer-to-int
int *bar; // bar is also pointer-to-int
In both cases, the type of the variable is "pointer-to-int"; "pointer-to-int" is a valid type.
Armed with that information, you can see that struct node* is a type, that type being "pointer-to-node-structure". Finally, therefore, the whole line
struct node* CopyList(struct node* head)
means "CopyList is a function taking a pointer-to-struct node (called head) and returning a pointer-to-struct node"
int *pointerName; is the same as int * pointerName; or int* pointerName;. The data type is int* in all those cases. So struct node* is just a pointer to struct node.
struct node* CopyList
To understand better you should read it from right to left. Which says CopyList is a function returning a pointer to node.
You can use '*' either with type or with function name/variable name.But it is suggested to use it with return type while declaring methods, like shown below
struct node* CopyList(struct node* head) {
/* code here */
}
when declaring pointers of a type use * with the variable name. like shown below,
int *ptr;
Declaring in that way increases readability.
For example consider this case,
int* a,b,c;
The above statement is appearing like declaring three pointer variables of base type integer, actually we know that it's equals to
int *a;
int b,c;
Keeping the * operator near the data type is causing the confusion here, So following the other way increases readability, but it is not wrong to use * in either way.
node* means that the following function/variable/structure has type 'pointer to type node'.

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.

Need some help with Linked Lists;

I have a simple question in understanding the pointers and struct definitions in the linked list code.
1)
typedef struct node
{
struct node* next;
int val;
}node;
here if I use two "node" when i initialize node *head; which node I am referring to?
2) Here I use an int val in the struct. If I use a void* instead of int is there any thing thats going to change ?
3)Also if I pass to a function
reverse(node* head)
{
node* temp = head; or node* temp = *head;
//what is the difference between the two
}
I am sorry if these are silly question I am new to c language.
Thanks & Regards,
Brett
<1>
in C you need to specify struct node for structs
struct node
{
...
} node;
the last 'node' is variable of type struct node
e.g.
node.val = 1;
and not a type.
if you want to use 'node' as a type you need to write
typedef struct node { .. } node;
<2>
if you use void* you will need a mechanism to handle what the pointers point to e.g. if void* points to an integer you need keep the integer either on the stack or the heap.
node n;
int value = 1;
n.val = &value; // pointing to a single integer on stack
int values[]={1,2,3};
n.val = values; // pointing to an array of integers on stack
void* ptr = malloc(sizeof(int));
n.val = ptr; // pointing to a single (uninit) integer allocated on heap
int* ptrval = (int*)ptr; // setting an int ptr to the same memory loc.
*ptrval = value; // ptrval now points to same as n.val does
<3>
reverse(node* head)
head is a pointer to your list, *head is the content of what the pointer points to (first node below)
head->[node next]->[node next]->[node
next]
EDIT: rephrased and edited.
EDITx2: apparently the question got edited and a typedef was added so the question was altered.
*head is the dereference of the pointer : ie the actual place in memory that is pointed to by the pointer head...
Think of head as a coat hanger and *head as the coat itself, if that helps.
ie:
struct * coat c; //this is a coat hanger, not a coat
....
struct coat k = *c;//this is the coat itself, not a coat hanger
For #1:
In C, struct's have a separate name space. So if you wrote:
struct foo { ... };
You then have to use struct foo to reference the type. If you tried just foo after the above definition, the compiler would give an error as it doesn't know anything about that unqualified name.
A typedef gives a type an alternate name. A typedef name does not need to be qualified, so once you do:
typedef struct foo foo;
You can now use an unqualified foo to reference the type. Since it's just an alternate name, you can now use struct foo and foo interchangeably.
For #2.
It's possible that if you changed val to a void * it could change the size of the entire structure. Whether that makes a difference will depend on how you've written the rest of your code.

Resources