I have a small program got from this link which pushes element into the stack.On careful examination I see that the storage space taken by this next pointer in the program for the first value ,second value,and third value is different.Can anyone please give me a satisfactory explanation for why it is happening like this.
I am using gcc compiler
#include <stdlib.h>
#include <stdio.h>
struct Node
{
int data;
struct Node *next;
};
int push_front( struct Node **head, int data )
{
struct Node *tmp = malloc( sizeof( struct Node ) );
int success = tmp != NULL;
if ( success )
{
tmp->data = data;
tmp->next = *head;
*head = tmp;
printf("\nAddress of pointer head now is %p for value %d",*head,data);
}
return success;
}
int main( void )
{
struct Node *head;
for ( int i = 0; i != 10; i++ ) push_front( &head, i );
return 0;
}
=======================================================================
output
-----
Address of pointer head now is 0x16f1010 for value 0
Address of pointer head now is 0x16f1440 for value 1
Address of pointer head now is 0x16f1460 for value 2
Address of pointer head now is 0x16f1480 for value 3
Address of pointer head now is 0x16f14a0 for value 4
Address of pointer head now is 0x16f14c0 for value 5
Address of pointer head now is 0x16f14e0 for value 6
Address of pointer head now is 0x16f1500 for value 7
Address of pointer head now is 0x16f1520 for value 8
Address of pointer head now is 0x16f1540 for value 9
The expectation is such that the header pointer should take equal bytes of address space while inserting each value.
malloc is used to dynamically allocate a contiguous block of memory of a given size. This memory is allocated from the heap.
malloc makes no guarantees that the memory allocated between two subsequent calls to malloc be contiguous.
Related
The following code below runs without a seg fault
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *data;
struct node *next;
};
int main(void)
{
struct node *head = malloc(sizeof(struct node));
head->data = "test";
printf("data: %s\n", head->data);
return 0;
}
when I switch the code to so
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *data;
struct node *next;
};
int main(void)
{
struct node *head = malloc(sizeof(struct node));
strncpy(head->data, "test", 512);
printf("data: %s\n", head->data);
return 0;
}
I receive a seg fault and am forced to switch my node property data to be of type char data[512]. Why is this required? I thought arrays are inherently pointers, so this behavior is not making sense to me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char data[512];
struct node *next;
};
int main(void)
{
struct node *head = malloc(sizeof(struct node));
strncpy(head->data, "test", 512);
printf("data: %s\n", head->data);
return 0;
}
I expected that both pointers and arrays could be assigned string values in the same way.
In this statement
head->data = "test";
the string literal having the array type char[5] is implicitly converted to pointer to its first element and this pointer is assigned to the pointer head->data.
In this statement
strncpy(head->data, "test", 512);
you are using an uninitialized pointer head->data and trying to copy the whole string literal to the memory pointed to by that pointer with an indeterminate value. That invokes undefined behavior.
I thought arrays are inherently pointers, so this behavior is not
making sense to me.
Arrays are not pointers. They can be implicitly converted to pointers to their first elements in most situations but this does not mean that arrays are pointers.
Consider the simple demonstration program below.
#include <stdio.h>
int main( void )
{
char data[512];
char *p = data;
printf( "sizeof( data ) = %zu\n", sizeof( data ) );
printf( "sizeof( p ) = %zu\n", sizeof( p ) );
}
Its output might look like
sizeof( data ) = 512
sizeof( p ) = 8
In the second snippet (the one that crashes), you allocate memory for the node struct, which includes the pointer data. However, this pointer is never initialized, and it points to some arbitrary memory address (or just NULL), meaning that writing to it is undefined behavior, and indeed likely to just segfault.
For it to point to a valid memory address, you'll have to explicitly allocate it:
struct node *head = malloc(sizeof(struct node));
head->data = malloc(sizeof(char) * 512 /* or some other size, of course */);
Why is this required? I thought arrays are inherently pointers, so this behavior is not making sense to me.
Pointers are just pointers and the only memory they occupy is the memory required to store an address. If you want a pointer to point at dynamically allocated memory, you need to allocate it yourself.
Example:
struct node {
char *data;
struct node *next;
};
struct node *create_node(const char *str) {
struct node *nn = malloc(sizeof *nn);
if(nn) {
nn->data = strdup(str); // allocate strlen(str)+1 bytes and copy the string
if(nn->data) { // strdup was successful
nn->next = NULL;
} else { // strdup failed
free(nn);
nn = NULL;
}
}
return nn;
}
void destroy_node(struct node *n) {
free(n->data);
free(n);
}
I thought arrays are inherently pointers
Array Vs pointer:
An array might decay to a pointer in expressions and function parameters, and array accesses might be rewritten by the compiler as pointer accesses, but they are not interchangeable. An array name is an address, and a pointer is the address of an address.
Why is this required?
Declaring a pointer only allocates memory for the pointer.
You can initialise a pointer in two ways:
Either with a string literal:
ptr = "abcd";
Originally, ptr was
indeterminate. But this changes
what it was pointing to such that
it now points to a string literal.
The compiler will store the
address of the first element of
the string literal in ptr.
If you were to do the same with an
array:
char s[] = "String";
and then try to change its value:
s = "String2";
/* error: assignment to expression
with array type */
It wouldn't compile, because
arrays, unlike pointers, are not
modifiable lvalues.
You can't change its value.
Or allocate memory for it and then
write to it.
errno = 0;
ptr = malloc (size);
if (!ptr) {
errno = ENOMEM;
perror ("malloc ()");
deal with error here...
}
Now you can use strcpy () to
copy to it.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct node {
int data;
struct node * next;
};
int main() {
struct node * head = (struct node * ) malloc(sizeof(struct node));
head -> data = 10;
head -> next = (struct node * ) malloc(sizeof(struct node));
head -> next -> data = 20;
head -> next -> next = NULL;
int noOfNodes = 2;
char * buff = malloc(50);
strncpy(buff, (char * ) & noOfNodes, sizeof(int));
// strncpy(buff+4,(char *)head,sizeof(struct node *));
memcpy(buff + 4, (char * ) head, sizeof(struct node * ));
printf("noOfNodes: %d\n\n", *(int * ) buff);
printf("1]<%p><%d>\n", head, head -> data);
printf("2]<%p><%d>\n\n", ((struct node * ) buff + 4), ((struct node * )(buff + 4)) -> data);
printf("address of next node \n");
printf("3]<%p>\n", head -> next);
printf("4]<%p>\n", ((struct node * )(buff + 4)) -> next);
return 0;
}
Ouput:
noOfNodes: 2
1]<0x56450bd632a0><10>
2]<0x56450bd63320><10>
address of next node
3]<0x56450bd632c0>
4]<(nil)>
why there is difference in address ?
1] ends with ...2a0
2] ends with ...320
if address is different then how come it pointing to the variable data(...->data) correctly ?
why is (buff+4)->next is NULL? it should be same as head->next (i.e. <0x56450bd632c0>).
struct node *n1 = head;
when we do this irrespective of how large the struct node this only needs 8bytes to store(as we are storing address of struct node).
i want to do this using memcpy() (using only 8 bytes)store only the address of struct node head and not all struct node in (buff+4).
how to do this ? thats why i used (struct node *).
[tl;dr] To copy the entire *head to buff+4 the memcpy line needs to be changed as follows.
memcpy(buff+4, (char *)head, sizeof(struct node)); // instead of sizeof(struct node *)
With OP's code, assuming the likely case of 32b integers and 64b pointers:
struct node is padded to satisfy the pointer alignment requirements
struct node
{
int data;
int hidden_padding_field; // <--- inserted by the compiler
struct node *next;
};
the following copies 8 bytes from head to buff+4, meaning head->data and hidden_padding_field get copied, but head->next does not.
memcpy(buff+4, (char *)head, sizeof(struct node *));
Consequently, the data value gets copied correctly, but the next pointer is left unitialized. That it happens to be NULL is entirely by accident, just one possible manifestation of undefined behavior.
why there is difference in address ?
Because the buff array is a different chunk of memory from the one that was malloced for the head, so buff+4 is a different place in memory.
if address is different then how come it pointing to the variable data(...->data) correctly ?
Because you memcpyd some memory into the buff at that location, copying it from the memory that head points at. So although it is a different chunk of memory, it has the same data written into it.
why is (buff+4)->next is NULL?
Because you did not copy enough memory, so the part where the next member should be is still whatever was in that part of the buff before the copy. This happened because you told memcpy to copy as much memory as a struct node * takes up; but you didn't want to copy a chunk of memory that was a pointer, you wanted to copy a chunk of memory that was the node itself. So it should have said sizeof(struct node) instead of sizeof(struct node *).
The struct node structure starts with int data, and int might be the same size as any ordinary pointer (at least, I can't think of any situations where it would be bigger). So when we look at the memory that starts at the location buff + 4, it seems we copied enough data there to put the correct value into the ->data, but not enough to do anything about the ->next.
This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 5 years ago.
I am currently trying to learn how linked lists as a personal project. I understand the core concepts and I have been trying to implement it into c. My program looks like it should work, keep in mind I am still new to programming :D
I created a structer pointer called head. head will point to the first node in the linked_list and startPtr will contain the address of head. Each time the function add is called a new node will be created and allocated some space in memory then the previously created node will point to the new node.
I know where my program is crashing but I can see why? It compiles fine.
My code crashes on the line
(*prevNode)->link = newNode;
This is the way I see this code:
I pass the double pointer startPtr into the function add. I then created a new node using malloc. Next I deference startPtr ( which is called prevNode in the function ) which should contain the memory address of head....right? I then use the "->" expression to point the the structure pointer inside head called link.
The program just ends at this point and I have no idea why. I have looked at other linked list c codes but most of them don't use double pointers they just declare global structers and pointers. I am using GCC as my compiler.
Anyone know why this is happening?
#include <stdio.h>
#include <stdlib.h>
// STRUCTURES
struct node
{
int data;
struct node *link;
}*head;
void add( int, struct node ** );
int main()
{
struct node *head;
struct node **startPtr;
startPtr = head;
struct node *nodePtr;
int userInput;
int inputData;
do{
printf( "\n\n1: enter new node\n" );
printf( "2: Print Nodes\n" );
printf( "\n\nEnter: " );
scanf( "%d", &userInput );
if ( userInput == 1 )
{
printf( "\n\nEnter data:");
scanf("%d", &inputData );
add( inputData, startPtr );
}
}while( userInput == 1 );
// printing linked list
nodePtr = head->link;
while( nodePtr->link != NULL )
{
printf( "%d\n", nodePtr->data);
nodePtr = nodePtr->link;
}
printf( "%d\n", nodePtr->data);
return 0;
}// END main()
void add( int num, struct node **prevNode )
{
// assigning memory for a new node
struct node *newNode = malloc( sizeof( struct node ) );
(*prevNode)->link = newNode;
newNode->data = num;
newNode->link = NULL;
prevNode = &newNode;
}// END add()
Also I have one other question which I couldn't find and answer to online. when I create a pointer to a structer e.g. struct node *ptr;. does the structer pointer my default store the address of it's self. by its self I mean the structer, so if I print ptr will it output the address of the structer ptr?
A lot to unpack here... these are uninitialized and then you alias a pointer rather than point to an address so you really don't have a pointer to a pointer you have 2 of the same pointer
struct node *head;
struct node **startPtr;
startPtr = head;
struct node *nodePtr;
maybe something like this:
struct node *head = NULL;
struct node **startPtr = &head;
struct node *nodePtr = NULL;
would be a better start... then in C you can't deref a NULL pointer so you have to check first if there is a possibility of a null pointer... note this wont check for uninitialized garbage values, which local variable can be:
if(startPtr && *startPtr)
{
// now you know you can deref startPtr twice,
// once to a pointer to an object (which might be null)
// then after then && you can deref to an actual object
}
Apart from this typo
startPtr = head;
^^^^
where has to be
startPtr = &head;
^^^^^
there are several problems with the code.
The first one is that the header was not initialized initially. So dereferencing this pointer results in undefined behavior.
The second problem is that this loop
do{
printf( "\n\n1: enter new node\n" );
printf( "2: Print Nodes\n" );
printf( "\n\nEnter: " );
scanf( "%d", &userInput );
if ( userInput == 1 )
{
printf( "\n\nEnter data:");
scanf("%d", &inputData );
add( inputData, startPtr );
}
}while( userInput == 1 );
is built logically incorrectly. For example if the user enters some number that is not equal to 1 or 2 then the program will try to output the list after exiting the loop.
The third one is as initially the header can be equal to null. So this statement in the function
(*prevNode)->link = newNode;
again invokes undefined behavior and moreover if *prevNode is not equal to NULL then all early appended nodes will be lost because its reference link is overwritten.
The function can look the following way
int add( struct node **head, int data )
{
struct node *newNode = malloc( sizeof( struct node ) );
int success = newNode != NULL;
if ( success )
{
newNode->data = data;
newNode->link = *head;
*head = newNode;
}
return success;
}
struct node *head;
never initialized
startPtr = head;
initialized to uninitialized; your entire program is undefined beyond this point.
This question already has answers here:
How can I allocate memory and return it (via a pointer-parameter) to the calling function?
(11 answers)
Closed 7 years ago.
I am having problem while initializing the node value to passed pointer in C language,
I have written something like follow,
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node *next;
};
void add(struct node *head, int val){
struct node *n1 = NULL;
n1 = (struct node *)malloc(sizeof(struct node ));
n1 -> data = val;
n1 -> next = NULL;
if(head == NULL){
head = n1;
printf("Head2 is initialized");
return;
}
}
int main(){
struct node *ptr = NULL;
struct node *temp;
add(ptr, 11);
printf("\nData = %d", ptr->data);
return 0;
}
Could you please tell me what is the issue in this code,
When i execute
printf("\nData = %d", ptr->data);
System shows Windows has stopped working
Thanks
short answer: if you want to change the value the pointer points to, you have to pass the pointer to the pointer:
void add(struct node **head, int val) {
...
if(*head == NULL){
*head = n1
}
int main(){
...
add(&ptr, 11)
...
}
long answer: when you call add(ptr, 11) in main you pass a memory address and a number. both memory address and a number are passed by value. as the result the changes to these variables are both local
in your add method - when you assign a value to head in head = n1 you change the value of your local variable to point to a new memory address. when your function returns the changes are gone, so main never sees the assignment and ptr remains NULL.
if you pass a pointer to ptr - &ptr, you will pass a location in memory where the value of ptr (which is memory address) resides in main, so when you call *head = n1* you write the address ofn1` the value in this location will change, and main will see it.
see also this question
A link is a pointer to a node
typedef struct node * link;
In main(), I have the following code (config->m is just some integer):
// array of pointers to structs
link heads[config->m];
// make memory for head nodes
for(i = 0; i < config->m; i++)
heads[i] = malloc(sizeof(struct node));
The code works (which is great). But is there a way I can allocate config->m pieces of memory without the loop? I tried
link heads[config->m];
heads = malloc(sizeof(struct node) * config->m);
but my friendly neighborhood compiler tells me incompatible types in assignment
I know I could use
struct node heads[config->m];
But I want to do this stuff with pointers.
And as always, someone will ask me if this is part of homework, and the answer is yes (sort of). But this particular chunk of code doesn't have anything to do with the actual assignment; it's for my own enlightenment. But thanks for asking :|
Nope, you need the loop. Your heads array is essentially a two dimensional array. You need at least two allocations. The first is the array of pointers:
link * heads = (link*)malloc (config->m * sizeof (link));
The second is the memory that each member of the heads array points to:
link buf = (link)malloc(sizeof(struct node) * config->m);
for(i = 0; i < config->m; i++)
heads[i] = &buf[i];
And then to de-allocate:
free(heads);
free(buf);
link heads[config->m];
link buffer = malloc(sizeof(struct node) * config->m);
for(i = 0; i < config->m; i++)
heads[i] = &buffer[i];
....
free(buffer);
On edit:
Actually, you don't need heads. First, let's get rid of link, as (see comments in Cannonade's answer) it just confuses the issue.
Let's pretend that a struct node is a node in an intrusive linked list, and looks like this:
struct node {
int val;
int filler[10]; // this is pure filler, to make node big
struct node* next;
};
Now we add our includes, and config->m:
#include <stdio.h>
#include <stdlib.h>
// your config->m
const int m = 10 ;
And in main() we print the sizeof a node:
int main() {
printf( "sizeof( struct node ) = %i\n", sizeof( struct node) );
Now we declare a pointer to node:
// na is a node pointer
struct node* na;
And malloc up m nodes. malloc returns the address of the array, whichis also the address of the first node in the array. We set na to the address malloc returned:
na = malloc(sizeof(struct node) * m);
Now we will use na, a pointer, as if it were an array. This works because C defines array[offset] as *(array + offset * sizeof(element))
int i;
// we give the first node a val of zero
na[0].val = 0;
// and a null next pointer
na[0].next = 0 ;
Now we'll walk up the rest of the array and set each node's next to the PREVIOUS node in the array:
for(i = 1; i < m; i++) {
na[i].val = i ;
// na[ offset ] is *(na + offset)
// we don't want to dereference,
// we want the address, so we use the
// address-of operator ("&")
na[i].next = &na[ i - 1 ];
}
Our head is the LAST node in the array na[ m - 1]. Each next in the list is the preceding node in the array. Again, we use the address-of operator if we want the pointer, instead of what's pointed to:
struct node* current = &na[ m - 1 ];
We'll print the address of each node. It should be the address of its next node pointer + sizeof( struct node), because each node is the node after (in the array) its next in the list ( the list is the array "reversed").
We cast it to char* to get a result in bytes. If we don't cast, we get the result in units of truct node* (which should always be 1).
while( current ) {
printf( "val %i, address of current %p, ", current->val, current) ;
printf( " address of current->next %p, ", current->next ) ;
if( current->next ) {
printf( " distance from next: ");
printf( "in bytes %i, ",
( (char*) current) - (char*) current->next ) ;
printf( " in struct nodes %i", current - current->next ) ;
}
printf( "\n" );
current = current->next;
}
return 0;
}
On my system, that gives this output:
sizeof( struct node ) = 48
val 9, address of current 0x804a1b8, address of current->next 0x804a188, distance from next: in bytes 48, in struct nodes 1
val 8, address of current 0x804a188, address of current->next 0x804a158, distance from next: in bytes 48, in struct nodes 1
val 7, address of current 0x804a158, address of current->next 0x804a128, distance from next: in bytes 48, in struct nodes 1
val 6, address of current 0x804a128, address of current->next 0x804a0f8, distance from next: in bytes 48, in struct nodes 1
val 5, address of current 0x804a0f8, address of current->next 0x804a0c8, distance from next: in bytes 48, in struct nodes 1
val 4, address of current 0x804a0c8, address of current->next 0x804a098, distance from next: in bytes 48, in struct nodes 1
val 3, address of current 0x804a098, address of current->next 0x804a068, distance from next: in bytes 48, in struct nodes 1
val 2, address of current 0x804a068, address of current->next 0x804a038, distance from next: in bytes 48, in struct nodes 1
val 1, address of current 0x804a038, address of current->next 0x804a008, distance from next: in bytes 48, in struct nodes 1
val 0, address of current 0x804a008, address of current->next (nil),