So I'm trying to understand how pointers work, especially with structs.
Here's the code I'm trying to understand
struct Node {
int val;
};
int main() {
Node* a = (Node*) malloc (sizeof(Node));
printf("%p\n", a);
printf("%p\n", &(a->val));
printf("%p\n", *a);
}
From my understanding if I print a, it would print the memory address of what was reserved by malloc. But I couldn't figure out which memory was being printed if I dereferenced a.
Here's the output.
00000000001C5D40
00000000001C5D40
00000000001C0150
I expected *a to be dereferencing the address of the first attribute. But as the output shows, it's not. So which memory is being dereferenced?
*a is the struct Node that a is pointing to. printf("%p\n", *a); passes the entire value of the struct Node. The “value” of a structure is an aggregate value composed of the values of all its members. In this case, there is just one member. And, since you did not assign any values to the member, its value is indeterminate.
However, for %p, you are intended to pass a pointer to printf (specifically a pointer of type void *). When you do not, the C standard does not define the behavior. The argument-passing mechanism may go awry in various ways. It might format the value in the member val as if it were a pointer and print that. Or it might print some unrelated data that happened to be a register where printf expected to find the pointer it should have been passed. Or your program could crash.
When you dereference a pointer to struct Node (*a) you get the struct Node variable itself. If you had not initialized it you can get whatever (garbage). So in your case (00000000001C0150) is some garbage that was at the moment in variable struct Node.
So I added one line in your code for clarity:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int val;
};
int main() {
struct Node* a = (struct Node*) malloc (sizeof(struct Node));
a->val = 1;
printf("%p\n", a);
printf("%p\n", &(a->val));
printf("%p\n", *a);
}
And I got the following result:
0xaaab04e522a0
0xaaab04e522a0
0x1
Hope, I help you a little bit)
Related
Im new to community this is my first post so hello to everyone.
I have recently started studying the coding and c language in specific.But i have a confusion when it comes to structures and how they are referenced in memory.
This is example when my lack of understanding makes me unable to understand what exactly happening in code.
For example when asking malloc for space for lets say a node structure the way i understood it until now is that computer will allocate memory of size of struct if instructed by size of operator in parenthesis. Therefore that many memory locations will be allocated starting at specific location pointer points to.But when we use pointer of struct type we allocated memory for (in this case struct node) it just stores a address of first byte of said struct as all pointers do if i understand correctly.
Then when
`*(pointername).exactfieldname
For example if we assume there is node structure defined in code.With two fields for int called numbers and for pointer called next.
node *n=malloc (sizeof(node));
*(n).next=malloc (sizeof(node));
syntax is used i cant understand how it works exactly.How is a computer just through pointer to a first byte out of certain number of bytes that were allocated suddenly able to access fields of structure?
Reason this is additionally confusing is because when defining a node struct for linked list for example it is possible to define pointer to struct of struct type being defined before it is defined because its just a pointer so it only stores address. Due to that fact struct pointer cant have any special property allowing it to access fields its still just a pointer right?
When pointer is derefrenced does it mean that computer goes to pointed location and enters a strucutres. And then rest of syntax after dereferencing pointer like *(pointer ).fieldname can be used because now computer is inside structure and interacts with it and .fieldname refers to that instruction now?
I'll try to answer despite your question lacking some clarity.
If I get you right, you are confused by this:
typedef struct node {
struct node *next; // <<<< here
some_type_t data;
} node;
In the line marked, the compiler does not yet know what struct node looks like.
That is correct. It doesn't need to know that because we only store a pointer.
In that place you cannot define a non-pointer element of that type (or any other incomplete type) for exactly that reason.
Now if you come to that part:
node *n=malloc (sizeof(node));
n->next=malloc (sizeof(node));
(Note: Your syntax was incorrect)
You seem to wonder how the compiler would know what n->next really is as it was unknown when the struct was defined.
That does not matter.
It is known when the compiler comes to this line. You can only dereference a pointer if the type is fully known in that location.
The compiler now knows what node* means and can address the fields in *n and in the same way it can deal with n->next.
Study and try do understand the following code.
Compare the values that are printed out. %p will print address values (hex format) and %d prints decimal values.
Take a good look at the parameters that are passed to the printf function. & is the 'address of' operator and -> is a dereference operator, which is equal to *(pointer)..
struct node {
struct node *next; //pointer to struct node
struct data_rec { //embedded struct
int value; //some value of type int
} data; //data of type struct data_rec
};
//allocation on the heap -> pointer to struct node
struct node *allocated_node = malloc(sizeof(struct node));
allocated_node->next = NULL;
allocated_node->data.value = 0;
//allocation on the stack (sizeof(struct node) bytes)
struct node base_node;
base_node.next = allocated_node;
base_node.data.value = 42;
//prints some information of the node
void printNodeInfo(struct node *node_)
{
printf(
"address of node: %p\n"
"address of node.next: %p\n"
"value of node.next: %p\n"
"address of node.data: %p\n"
"address of node.data.value: %p\n"
"value of node.data.value: %d\n",
node_,
&node_->next,
node_->next,
&node_->data,
&node_->data.value,
node_->data.value
);
}
int main()
{
printNodeInfo(&base_node);
printNodeInfo(allocated_node);
return 0;
}
Do pointers to structures in C work differently than other pointers?
For example in this code:
typedef struct node {
int data;
struct node *next;
} node;
void insert(node **head, int data) {
node *new_node = malloc(sizeof(node));
new_node->data = data;
new_node->next = *head;
*head = new_node;
}
int main() {
node *head = NULL;
insert(&head, 6);
Why do I have to use a pointer to a pointer and can't use the variable head in the insert function like in this example with arrays:
void moidify(int *arr) {
*arr = 3;
}
int main() {
int *array = malloc(8);
*array = 1;
*(array + 1) = 2;
moidify(array);
}
Here I don't have to pass &array to the function.
There is no difference. If you want to change the value of the variable you send in to function in such a way that the change is visible in the function that called function, you need to supply its address to function, which is what you do when taking the address of head.
In moidify(array) you send in a pointer to the first element in array which is why modifying the array data works. If you would like to modify the array variable itself (by making it potentially point somewhere else), you would have to take its address too. Example:
void moidify(int **arr) {
*arr = realloc(*arr, 128);
if(*arr == NULL) {
perror(__func__);
exit(1);
}
}
int main() {
int *array = malloc(8);
*array = 1;
*(array + 1) = 2;
moidify(&array);
}
You must understand how pointers works to get this one.
Here, the variable array is not properly speaking, an array. It's a pointer toward a memory space, of size 8 * sizeof(int). It contains only an address. From this address you can access the values of the array, you move using this address, to the rightfully memory space you want to fill or read.
Once that understood, when you call the moidify function, you are not passing the array. Nor the memory space. You are passing, the address of the memory space. The function gets a copy of the given address, in the argument variable int *arr.
Hence, you can use it the same way you use it from the main function.
If you wanted to change the address toward which the array variable would go, you would need to specify &array to the receiving function, which would then use an int ** argument variable.
Your example with struct is similar to this last part I just described, you want to change toward which address head is pointing, so, you need to give &head to the function. To get the address of head, and be able to modify the contained address.
You use an address, to access the memory space called head, to modify the address inside the memory space called head, which point toward another memory space, where your struct truly belongs.
List.c
int const LIST_SIZE = 100;
typedef struct node {
void *item;
} Node;
typedef struct list {
Node *currentItem;
Node *items[LIST_SIZE];
} LIST;
main.c
#include <stdlib.h>
#include <printf.h>
#include "List.h"
LIST *ListCreate();
int main() {
LIST *newList = ListCreate();
Node *newNode = malloc(sizeof(Node));
newList->currentItem = newNode;
newNode->item = (int *)200;
printf("%d", *((int *)newNode));
}
LIST *ListCreate() {
LIST *newList = malloc(sizeof(LIST));
return newList;
}
My question is:
In main.c, I use the printf statement to access the item in the newNode. According to my understanding the proper call should be:
printf("%d", *((int *)newNode->item));
However, I get a segmentation fault when using this. Could anyone please explain me why this doesn't work and the other one works?
Thanks.
(int*)200 tells the compiler to take the number 200 and pretend it's the address of an int. However, it's not actually a valid address of an int, so you can't dereference it (i.e. you can't use *(int*)newNode->item to get the int at that address).
All you want to do is tell the compiler to take the "address" and treat it as a number again, which you can do using:
printf("%d", (int)newNode->item);
The (int) cast undoes the (int*) cast from before.
Side note: using (int*) here is slightly unusual; there's no reason to use it instead of (void*).
You're storing 200 (which isn't a pointer value) in the pointer variable, and then you deference the variable as a pointer even though it doesn't actually contains a pointer value.
General pattern for some type type:
Node* node = malloc(sizeof(Node));
node->item = malloc(sizeof(type));
*((type*)node->item) = ...;
type val = *((type*)node->item);
free(node->item);
free(node);
So, to store an int, it would be
Node* node = malloc(sizeof(Node));
node->item = malloc(sizeof(int));
*((int*)node->item) = 200;
printf("%d\n", *((int*)node->item));
free(node->item);
free(node);
Now, pointers can be used to store integers, so you could save an allocation in this particular case by using some trickery. This is a more advanced solution.
Node* node = malloc(sizeof(Node));
node->item = (void*)200; // Store the number in a pointer variable.
printf("%d\n", (int)node->item); // Treat the pointer variable as an `int`.
free(node);
Making a slight change to the main() lets take a look at this application run using Visual Studio 2013 in debug mode.
The modified main() is as follows:
int main() {
LIST *newList = ListCreate();
Node *newNode = malloc(sizeof(Node));
newList->currentItem = newNode;
newNode->item = (int *)200; // assign the value 200 to the pointer item
printf("*((int *)newNode) %d\n", *((int *)newNode)); // works
printf("((int)newNode->item) %d\n", ((int)newNode->item)); // works
printf("*((int *)newNode->item) %d\n", *((int *)newNode->item)); // access violation exception
}
When this console application is run, the window displayed contains two lines of output:
*((int *)newNode) 200
((int)newNode->item) 200
In the debugger, when single stepping through the function main() an access violation exception is thrown on the indicated line. The actual text of the access violation is:
First-chance exception at 0x010E1BAF in ConsoleApplication1.exe: 0xC0000005: Access violation reading location 0x000000C8.
Unhandled exception at 0x010E1BAF in ConsoleApplication1.exe: 0xC0000005: Access violation reading location 0x000000C8.
The location being read, 0x000000C8, is the decimal number 200 and when an attempt is made to dereference the pointer item as an int pointer containing the value of 200, the memory location of 200 is not valid for this application running under Windows 10 in user mode.
*((int *)newNode) means to treat the value of the variable newNode as a pointer to an int and to then fetch the value at that address. This works because newNode contains an address this application can access.
(int)newNode->item means to treat the value of the variable newNode->item as an int and to fetch the value of that variable. The variable is not treated as a pointer but as a variable containing an int.
*((int *)newNode->item) means to to treat the value of the variable newNode->item as a pointer to an int and to then fetch the value at that address. This doesn't work because the value of the variable newNode->item, a value of 200, is not an address this application can access so an access exception is thrown when the attempt is made.
According to my understanding the proper call should be:
printf("%d", *((int *)newNode->item));
That is true only from a syntactic point of view. But it is wrong because you are not using pointers correctly.
newNode->item = (int *)200;
Not sure what you were expecting that line to do. Casting 200 to an int* does not give you a valid pointer.
*((int *)newNode->item
only dereferences the value 200 pretending to be a valid pointer. This causes undefined behavior.
You can use:
// Allocate memory for newNode->item
newNode->item = malloc(sizeof(int));
// Set the value
*((int *)newNode->item) = 200;
// Print the value
printf("%d", *((int *)newNode->item));
Unless you wish to store other kinds of object in a node, I suggest using:
typedef struct node {
int item;
} Node;
and then your code can be a little bit simpler.
// Set the value
*newNode->item = 200;
// Print the value
printf("%d", newNode->item);
I am creating a linked list with a for loop and doing malloc inside the for loop. The problem I got is inside the for loop, malloc always returns the same memory address!
I thought it should return a different address every iteration so that I can link the nodes. The current output means the program is always overwriting the same address and I cannot link the nodes, because there is only one node all the time. Is it correct?
struct list_node {
char *id;
char *url;
struct list_node *next;
};
int main(void) {
int j;
for (j = 0; j < 5; j++) {
struct list_node *new_node = malloc(sizeof(struct list_node));
printf("No %d has address %p\n", j, &new_node);
}
}
=>
No 0 has address 0x7fff5db122b0
No 1 has address 0x7fff5db122b0
No 2 has address 0x7fff5db122b0
No 3 has address 0x7fff5db122b0
No 4 has address 0x7fff5db122b0
Anyone has a clue for this?
You're printing &new_node, the address of the pointer, not the pointer itself. In your case, &new_node is a constant value for one runtime.
If you want to print the pointer returned by malloc(), just supply the variable new_node, and cast it to void *.
That said, just a word of advice, despite being a snippet, you're missing out free() calls. It's causing memory leak.
You are printing &newnode. This is the address of the pointer. This will always be the same.
What will change is the value in the pointer newnode.
If you print
printf("No %d has address %p\n", j, new_node);
You should get a different value each time, as expected.
I am trying to assign the address of one of a structure, which is named as node, to another one named tmp, which has the same type--Node. However, the address of tmp is always less 8 then the address of node. Why is that? thanks!
#include <stdio.h>
#include <stdlib.h>
typedef struct _node
{
int data;
struct _node *next;
}Node;
int main()
{
Node *node = (Node*)malloc(sizeof(Node));
Node *tmp;
tmp = node;
printf("%d\n",&node);
printf("%d\n",&tmp);
}
I am guessing that you expected the output to be the same for both lines.
For that to happen, you have to print the values of the pointers, not the addresses of the pointers.
After
tmp = node;
the value of tmp is the same as the value of node but the addresses of the two variables are always going to be different.
I suspect you meant to use:
printf("%p\n", node); // Use %p for pointers, not %d
printf("%p\n", tmp);
Likely pointers are 8 bytes on your platform. So since you allocated one right after the other, they are 8 bytes apart.
You are confused about the difference between the value of a variable (of pointer type) and its address. You can change the value of a variable, as you do in your code by means of the assignment operator:
tmp = node;
but a variable's address is the most essential of its defining characteristics. You cannot change that.
You are printing the addresses of your pointers (sort of -- the field descriptors in your format string are wrong). To print their values, you want this:
printf("%p\n", (void *) node);
printf("%p\n", (void *) tmp);
The key distinction is of course that the above does not employ the address-of operator (&). Additionally, the %p field descriptor is what you need to print a pointer value, but it is specifically for void * values. And that's the reason for the casts.