Pointer to declared but uninitialized variable in C - c

I've been reviewing the basics of singly linked list In C with materials from Stanford CS Library, where I came cross the following code:
struct node{
int data;
struct node* next;
};
struct node* BuildWithDummyNode(){
struct node dummy;
struct node* tail = & dummy; // this line got me confused
int i;
dummy.next = NULL;
for (i=1;i<6;i++){
Push(&(tail->next), i);
tail = tail->next;
}
return dummy.next;
}
Probably not revenant, but the code for Push() is:
void Push(struct node** headRef, int data){
struct node* NewNode = malloc(sizeof(struct node));
newNode->data = data;
newNode->next = *headRef;
*headRef = newNode;
}
Everything runs smoothly, but I've always been under the impression that whenever you define a pointer, it must point to an already defined variable. But here the variable "dummy" is only declared and not initialized. Shouldn't that generate some kind of warning at least?
I know some variables are initialized to 0 by default, and after printing dummy.data it indeed prints 0. So is this an instance of "doable but bad practice", or am I missing something entirely?
Thank you very much!

Variable dummy has already been declared in the following statement:
struct node dummy;
which means that memory has been allocated to it. In other words, this means that it now has an address associated with it. Hence the pointer tail declared in following line:
struct node* tail = & dummy;
to store its address makes perfect sense.

"But here the variable "dummy" is only declared and not initialized."
The variable declaration introduces it into the scope. You are correct in deducing it's value is unspecified, but to take and use its address is well defined from the moment it comes into scope, right up until it goes out of scope.
To put more simply: your program is correct because you don't depend on the variables uninitialized value, but rather on its well defined address.

Related

init() function call in C

I am following an online tutorial which presents me with the following (simplified) code:
typedef struct {
int data;
Node* next;
} Node;
int main(){
Node *head;
init(&head);
return 0;
}
What is the purpose & functionality of the init function? I did not define it myself, however am struggling to find documentation online as well.
For starters this declaration
typedef struct {
int data;
Node* next;
} Node;
is incorrect. The name Node used in this data member declaration
Node* next;
is undefined.
You need to write
typedef struct Node {
int data;
struct Node* next;
} Node;
As for your question then in this declaration
Node *head;
the pointer head has an indeterminate value because it is not initialized.
So it seems the function init just initializes the pointer. You need to pass the pointer by reference through a pointer to it. Otherwise the function will deal with a copy of the pointer head. Dereferencing the pointer to pointer you will get a direct access to the original pointer head that can be changed within the function. That is the function can look the following way
void init( Node **head )
{
*head = NULL;
}
Pay attention to that you could just write in main
Node *head = NULL;
without a need to call the function init.
I think that the init function is gonna be implemented in the next videos. I suppose that your teacher wants to use an init function to set some values if you create a new Node (or a struct in this case) to prevent some easter eggs undefined behaviour.

pointers don't change after i modified it

I'm setting up a struct called Node
typedef struct node{
struct node *left;
struct node *right;
struct node *parent;
}node;
and a function that operate on the nodes:
int test(node *old,node* new){
old->parent->right = new;
new->parent = old->parent;
}
Ok, so i make 3 nodes and set up the relationship between them
node* me =malloc(sizeof(node));
node* me1 = malloc(sizeof(node));
node* me2 = malloc(sizeof(node));
me->right = me1;
me->left = me2;
me1->parent = me;
me2->parent = me;
test(me1,me);
1.However, after test(), me1->parent->right changed while me1 didn't, which is weird because me1 and me1->parent->right point are the same address. I wonder if i make any wrong assumption here?
2.In function test(), if i replace old->parent->right with old only, then after the function call, the node me1 remains the same. Isn't the pointer modified after we do operations on it inside a function,and why in this case it is not?
me, me1, and me2 are local variables inside your outer function (let's assume it was main). These pointers are never modified, so after the call to test, me1 still points to the same node as before, while the pointer me1->parent->right now points to me. So, "me1 and me1->parent->right point are the same address" isn't true anymore!
If you only modify old inside test, you will only modify the parameter old, which is a copy of me1. After test returns, this copy is forgotten, and the modification has no effect. If you want to modify the me1 variable from within test, you will have to pass a pointer to the pointer, i.e. a double pointer:
int test(node **old,node* new){
*old = new;
...
}
and call it as test(&me1,me);.
Also: Please don't name things "new", because if you ever decide to compile the code as C++, this will conflict with the reserved keyword new.
Here is what your test() method does:
int test(node *old,node* new){
old->parent->right = new;
new->parent = old->parent;
}
when you call this:
me->right = me1;
me1->parent = me;
test(me1,me);
These steps happens:
me1's parent is me and me's right is me1. So me's right becomes me again.
me's parent becomes me itself.

cc compiler issue in C

I am trying to write a simple code to construct a tree in C language. Below is my code snippet.
#include<stdio.h>
struct node
{
int data;
struct node *left;
struct node *right;
};
int main()
{
struct node *root = newNode(5);
//struct node *root = NULL; working piece
//newNode(&root,5); working piece
if(root == NULL)
{
printf("No root\n");
return 0;
}
//root->left = newNode(4);
//root->right = newNode(3);
//root->left->left = newNode(2);
//root->right->right = newNode(1);
return 0;
}
struct node* newNode(int data)
{
struct node *temp;
temp = (struct node*) malloc(sizeof(struct node));
temp->data = data;
temp->left = NULL;
temp->right = NULL;
return(temp);
}
When I try to return the structure node address, the compiler gives me the error
"rightNode.c", line 29: identifier redeclared: newNode
current : function(int) returning pointer to struct node {int data, pointer to struct node {..} left, pointer to struct node {..} right}
previous: function() returning int : "rightNode.c", line 12
But when I comment this struct node* newNode(int data) and try to define a function that returns int by passing the address of the structure to the function like below, it does not shows me any error.
int newNode(struct node **root,int data)
{
printf("Inside New Node\n");
return 0;
}
As far I know, it is legal in C to return the address of the structure to the calling function.
It is something to do with the compiler.
I am using cc compiler in unix environment
type cc
cc is a tracked alias for /apps/pcfn/pkgs/studio10/SUNWspro/bin/cc
Below is the command I used to compile cc rightNode.c
Any help would be appreciated...
You need to declare a newNode prototype before you use it.
// somewhere after struct node definition and before first use
struct node* newNode(int);
You also need to include stdlib.h to get malloc.
Put this struct node* newNode(int data) above the code and include stdlib.h.
You need a function prototype if you are going to use a function before you declare it. Also malloc is defined in stdlib.h.
There is no function prototype visible when you call struct node *root = newNode(5); so the compiler gets confused.
When the compiler cannot find a function declaration, it assumes that such function exists, but returning int. Declare struct node* newNode(int data); before you call newNode(...) in main.
In older versions of C, you did not need to declare a function before using it. In older C, functions that are not declared are assumed to return int and accept an unspecified number of arguments. This is the reason you are getting the error, because the compiler assumes the newNode function returns int, rather than struct node *.
In modern C (C99 and newer), you can no longer do this. You must declare functions before they are used. Some compilers still allow the old behaviour and warn against it, but a strictly conforming C99 program cannot use a function without declaring it first.
In your case, you should put the following line of code before your main function. This tells the compiler about the newNode function and how it should be called:
struct node *newNode(int);

Why is this simple hello world code segfaulting?

Excuse the beginner level of this question. I have the following simple code, but it does not seem to run. It gets a segmentation fault. If I replace the pointer with a simple call to the actual variable, it runs fine... I'm not sure why.
struct node
{
int x;
struct node *left;
struct node *right;
};
int main()
{
struct node *root;
root->x = 42;
printf("Hello world. %d", root->x);
getchar();
return 0;
}
What is wrong with this code?
struct node *root;
root->x = 42;
You're dereferencing an uninitialized pointer. To allocate storage for the node:
struct node *root = malloc(sizeof(struct node));
You could also allocate a node on the stack:
struct node root;
root.x = 42;
In order to use a pointer to access something, the pointer must be pointing at that something. In order for the pointer to be pointing at that something, that something must exist. Creating a pointer does not create anything for it to point at. You must do so explicitly, either by dynamic allocation (malloc()), stack allocation (i.e. a local variable) or by pointing to something that already exists (e.g. a static instance, such as a global; a value that was passed in as a parameter; etc.).
After struct node *root; line add the
root = (sturct node*) malloc(sizeof(struct node));
Also, before Return 0 line add the
free(root);

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