Consider:
#include<stdlib.h>
#include<stdio.h>
struct node {
int val;
struct node *next;
};
typedef struct node item;
void main() {
item * curr, *head;
int i;
head = NULL;
for (i = 1; i <= 10; i++) {
curr = (item *)malloc(sizeof(item));
curr->val = i;
curr->next = head;
head = curr;
}
curr = head;
while (curr) {
printf("%d\n", curr->val);
printf("%d\n", *curr);
curr = curr->next;
}
getchar();
}
As I print out, *curr
and curr->val
are the same. Why?
I am confused about *curr
. I think *curr
is the value &curr
points to. (I am newbie in C.)
In C, the address of a struct can be cast to an address to its first element. So (void *) &curr is the same as (void *) &(curr->val) . Here I cast everything to void * to make sure to have compatible pointer types. That means that *((int *) curr) is a perfectly defined C expression and its value is indeed curr->val .
A "node" is a concept from graph theory. A graph consists of nodes (vertices) and edges that connect the nodes. A node in C can be represented as a structure (a struct ) that has all the necessary data elements "on board" to implement a graph. Optionally a structure may be required that represents the edges.
First as a beginner, you should try to write correct code that raises no warning before trying to understand what happens under the hood and why some incorrect expressions still give correct results.
C is a very permissive language, that is as long as the compiler can translate what it reads it generally assumes that the programmer knows why he wrote it. It's what happens here.
In C, the address of a struct
can be cast to an address to its first element. So (void *) &curr
is the same as (void *) &(curr->val)
. Here I cast everything to void *
to make sure to have compatible pointer types.
That means that *((int *) curr)
is a perfectly defined C expression and its value is indeed curr->val
. But it is correct, because I wrote an explicit pointer cast.
What you wrote works only by accident, because as curr
is an aggregate type; you pass an int
and an item *
to printf
and use only its first value - this is no longer standard C and I can only assume a classic implementation to guess that. But just replace your print commands by that:
printf("%d - %d\n", curr->val, 12);
printf("%d - %d\n", *curr, 15);
You should see garbage in the second printf
, because with %d
you declare that you pass a simple int
and actually pass an aggregate. Here again, nothing is explicitly mandated per standard, but common implementation should give this result.
TL;DR: As *curr
is not an int
, printf("%d\n", *curr);
is Undefined Behaviour. This means that anything can happen, even the expected result, but a different version of same compiler, or another compiler, or even a change in compilation parameters could give a different result, as could a minor change in the code.
And C allows automatic pointer cast to and from void *
and you should never cast the return value of malloc
as it can hide bugs. Please write:
curr = malloc(sizeof(item));
It is no longer C++ compatible, but is it correct C.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With