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.
Related
I have this struct in c
struct node{
int info;
struct node* link;
};
this procedure:
void example(struct node** head){
struct node* tmp;
tmp=*head;
tmp->info=0;
*head=tmp;
}
and call the procedure in the main with
example(&head);
so to modify head->info I need a support variable,there is another way without a support variable?
Use this:
void example(struct node** head){
(*head)->info=100;
}
It'll do the same as your example function.
By dereferencing struct node** we get struct node*, then we can simply access it's member by using -> arrow operator.
If you have a pointer to an object declared like
struct node *head;
head = malloc( sizeof( struct head ) );
then you can just write
head->info = 10;
So as the object info is passed by reference to the function example there is no great sense to declare the parameter of the function as pointer to pointer
void example(struct node** head){
^^^^^^^^^^^
You can define the function like
void example(struct node *head){
head->info=0;
}
You need to pass head by reference when head itself is changed in the function.
For example
void insert( struct node **head, int info )
{
struct node *tmp = malloc( sizeof( struct node ) );
tmp->link = *head;
tmp->info = info
*head = tmp;
//^^^^^^^^^^^
}
If you need to change the data member info using pointer to pointer head then at first you need to dereference it to get pointer to the object info like and then apply the operator ->. For example
( *head )->info = 0;
In C if you want to change an object (that in particularly can be a pointer) in a function you have to pass it by reference that in C means passing an object through a pointer to it.
The following piece of code does not compile in Eclipse:
typedef int Data;
typedef struct node* Node;
typedef struct node {
Data data;
Node next;
};
int main() {
Node n = newNode();
return 0;
}
Node newNode() {
Node newNod;
newNod = malloc(sizeof(struct node));
if(!newNod){
return NULL;
printf("\naa");
}
newNod->data = 3;
return newNod;
}
The one error displayed on compile time is
error: conflicting types for 'newNode'* (line with newNode() method declaration "Node newNode() {").
I'm clueless. What's wrong?
Move the definition of newNode above main [or add a forward declaration of newNode above main].
In your code, when the compiler sees the call to newNode in main, it is using an implicit declaration. When the actual definition is encountered, it doesn't match that
The statement
typedef struct node {
Data data;
Node next;
};
is not correct. The typedef requires a name for the type like you did in typedef struct node* Node;.
Since you only want to define struct node without a typedef, you should remove the word typedef in this statement:
struct node {
Data data;
Node next;
};
There is an ancient idea, prior to the c language being standardized where a function that has been called but not yet declared, is implicitly declared. In such declaration the return value would be int by default.
After the implicit declaration, comes the definition so the compiler is confused.
There are 2 solutions to this,
Delcare the function before main(), i.e. add
Node newNode();
before main().
Move the entire newNode() definition before main().
Now that we've addressed the problem, please note that typedefing a pointer is a bad idea. It's not immediately clear from the code that variables of such type are really pointers. And since there's a very important difference whether they are pointers or not, you should make it as clear as possible.
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.
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);
I get this weird side effect while using operator '->' in code I wrote in C. The pointer which I used -> on , is changed to have some garbage.
More specifically:
I have the following structs:
typedef void* ListElement ;
typedef struct List_t* List ;
typedef struct Node_t* Node;
Struct Node_t {
ListElement data ;
Node next;
}
Struct List_t {
Node* head;
Node* current
}
when I use the following ListGetFirst(), I get wired behavior :
ListElement ListGetFirst(List list)
{
if( list == NULL || list->head==NULL)
{
return NULL;
}
list->current=list->head;
Node* head =list->head; // here is the problem
ListElement data = (*head)->data;
return data;
}
when I used debugger I figured out that the pointer list->head is changed on the marked aformentioned line .
I realy have no idea why, and I didn't knew that '->' can have side effect
thanks in advance
Are you sure this is exactly what you want to do?
typedef struct Node_t* Node;
Node* head =list->head;
Since you defined Node as a pointer to Node_t, shouldn't you be doing:
Node head =list->head;
EDIT:
To summarize the whole thing, I think this typedef is misleading you:
typedef struct Node_t* Node;
It would made more sense if it were simply:
typedef struct Node_t Node;
Gah, pointers hidden behind typedefs; unless the type's meant to be totally opaque, that's almost always bad juju. For my benefit, I'm going to take out the typedefs so I have an easier time seeing what you're really playing with.
struct Node_t {
void *data ;
struct Node_t *next;
};
struct List_t {
struct Node_t **head;
struct Node_t **current;
};
void *ListGetFirst(struct List_t *list)
{
if( list == NULL || list->head==NULL
{
return NULL;
}
list->current=list->head;
struct Node_t **head =list->head; // here is the problem
void *data = (*head)->data;
return data;
}
I got nuthin'. Types all appear to match up. The -> operator most emphatically does not have any side effects; all it does is dereference a pointer. The extra level of indirection for head and current in struct List_t is a head-scratcher, and it makes me wonder if they're being allocated or assigned correctly. All I can figure is that list->head isn't pointing to memory that you actually own, and is getting overwritten somehow when you reach that point (IOW, you've invoked undefined behavior somewhere else in your code).
In short, the problem isn't in the code that you've posted. It's probably where you allocate and assign list elements.
You are using pointers to pointers, where most likely you want pointers.
In List_t you define head as Node*, where Node is already a Node_t* .
hth
Mario