I have this defined struct:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* prev;
struct Node* next;
} Node;
typedef struct List {
int size = 0;
Node* head = NULL;
Node* tai = NULL;
} List;
List* list1;
For the the node one it is Ok, but for the List one I have a declaration error in visual studio (2022), I am new to C, how to declare default values in C structs?
In C, whether an object is initialized or not depends on how you declare the object, for example whether you declare it as an object of static storage duration (which is initialized to zero unless you explicitly initialize it to something else) or an object of automatic storage duration (which is not initialized, unless you explicitly initialize it).
Therefore, it would not make sense to assign default values to the type definition, because even if the language allowed this, it would not guarantee that the object of that type will be initialized.
However, you can create your own function which initializes your struct to specific values:
void init_list( List *p )
{
p->size = 0;
p->head = NULL;
p->tail = NULL;
}
Assuming that the object is declared inside a function (not at file scope), you can use the following code to declare and initialize the object to default values:
List list1;
init_list( &list1 );
If the object is declared at file scope, you can't call the function init_list at file scope, but you can call the function inside the function main, for example.
Alternatively, when you declare the object, you can also initialize the individual members:
List list1 = { 0, NULL, NULL };
This will also work at file scope.
Since everything is being initialized to zero, it is sufficient to write the following:
List list1 = { 0 };
In that case, all members that are not explicitly assigned a value will be initialized to zero.
In C opposite to C++ you may not initialize data members in structure declarations like you are doing
typedef struct List {
int size = 0;
Node* head = NULL;
Node* tai = NULL;
} List;
Also it does not make sense to declare the global pointer list1.
List* list1;
What you need is to write
typedef struct List {
int size;
Node* head;
Node* tail; // I think you mean `tail` instead of `tai`
} List;
int main( void )
{
List list1 = { .size = 0, .head = NULL, .tail = NULL };
//...;
In C you can't define a struct with default values for the members.
You can however create a global instance with the default values set that you then use for initialization. That's pretty common in the C world.
Example:
typedef struct List {
int size;
Node* head;
Node* tail;
} List;
// The init-value to use
const List List_INIT = {.size = 0, .head = NULL, .tail = NULL};
int main() {
List l = List_INIT; // using the init-value
}
typedef struct List {
int size;
Node* head;
Node* tail;
} List;
What you have defined here is a new data type, you haven't declared any variables of such a type. The name List is not a variable, it is the name of a structure type. The names size, head and tail are not variables, they're the identifiers for the members of this struct.
How to declare default values in C structs?
You can not define a type with default value for the members. Simply provide a definition for it with/after declaration:
List apple;
memset (&apple, 0x00, sizeof apple);
/* Or */
List apple = { .size = 0, .head = NULL, .tail = NULL };
/* Or */
List apple = { .size = 0, .head = 0, .tail = 0 };
/* Or */
List mango = { 0, NULL, NULL };
/* Or */
List banana = { 0, 0, 0};
/* Or */
List orange = { 0 };¹
[1] — §6.7.9 Initialization:
If there are fewer initializers in a brace-enclosed list than there
are elements or members of an aggregate, or fewer characters in a
string literal used to initialize an array of known size than there
are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage
duration
Related
I'm trying to write a function generate_list which will generate a list with one node initialized to with val as 0 and next as NULL. generate_list should not take any arguments.
Here are the requirements:
define a struct datatype named node which contains an integer number and a pointer to the next node of the list.
define a new datatype named list, defined as a pointer to the node. list represents the list's head.
define a function of type list called generate_list which takes no parameters and returns a list with a dummy node (integer number = 0, pointer = NULL).
I tried something like this:
typedef struct list_node {
int val;
struct list_node *next;
}
typedef struct a_list {
node *head;
}
list generate_list() {
list *l = malloc(sizeof(*l));
node d_node;
l->head = &d_node;
d_node.val = 0;
d_node.next = NULL;
return *l;
}
I am not sure if I did correctly the second part and how could I implement the function?
what should I return from it?
There are some problems in your code:
you should include <stdlib.h>
the type definitions must include the type name and end with a ;
the argument list of generate_list should be defined as (void), not () which has a different meaning in C (unlike C++).
the first node should be allocated, not an automatic variable that will become invalid as soon as the function returns.
the list itself should not be allocated, but returned by value, a peculiar requirement that is explicit in the problem specification.
Here is a modified version:
#include <stdlib.h>
typedef struct node {
int val;
struct node *next;
} node;
typedef struct list {
node *head;
} list;
list generate_list(void) {
list l;
l.head = malloc(sizeof(*n));
if (l.head == NULL) {
/* abort with an error message */
perror("generate_list");
exit(1);
}
l.head->val = 0;
l.head->next = NULL;
return l;
}
you actually did pretty well. But, you must return a pointer to the list from your generate_list function.
It should be like this:
a_list *generate_list(void)
{
a_list *list = (a_list *)malloc(sizeof(a_list));
list_node *head_node = (list_node *)malloc(sizeof(list_node);
list->head = head_node;
head_node->val = 0;
head_node->next = NULL;
return list;
}
now you want to generate your list inside the function. but, you also want to return an accessible list. Hence, you must malloc it all (the list and the node) so it wouldn't be a local variable (allocated on the stack and disappear after the function returns).
I've been learning C for a month now and I've learned/remember that functions are defined like this:
return_type function_name( parameter list ) {
...body
}
But in a lecture about 'list ADTs' the example code which illustrates making and printing a full list there were some pieces of code(function declarations) in a form that I've never seen.
...
typedef struct list{ int data; struct list *next; } list;
list* create_list(int d) {
...
}
To my understanding the return type is ' list '(?) which is a structure tag, and the function name is ' * create_list ' (which is a dereferenced pointer??). I couldn't understand why it was written like that. I want to know how it works and how to use it. How does it differ from other (normal looking)functions like struct create_list(int d) {...}? The instructor didn't mention or explain about these so I'm quite confused.
here is the full code just in case
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
typedef struct list{ int data; struct list *next;} list;
int is_empty(const list *l) { return (l == NULL); }
list* create_list(int d) {
list* head = malloc(sizeof(list));
head -> data = d;
head -> next = NULL;
return head;
}
list* add_to_front(int d, list* h) {
list* head = create_list(d);
head -> next = h;
return head;
}
list* array_to_list(int d[], int size) {
list* head = create_list(d[0]);
int i;
for(i = 1; i < size; i++) {
head = add_to_front(d[i], head);
}
return head;
}
void print_list(list *h, char *title) {
printf("%s\n", title);
while (h != NULL) {
printf ("%d :", h -> data);
h = h -> next;
}
}
int main() {
list list_of_int;
list* head = NULL;
int data[6] = {2,3,5,7,8,9};
head = array_to_list(data, 6);
print_list(head, "single element list");
printf("\n\n");
return 0;
}
any help would be appreciated!
Please correct me if I'm wrong in some point. Thank you
You're close, but reading it wrong. Function names do not have things like * in them, only types do.
This defines a function that returns list* (a.k.a. struct list* which is what typedef establishes earlier) given argument d of type int:
list* create_list(int d) {
// ...
}
In other words, create_list returns a pointer to list. In a type definition * means pointer, but it has a different meaning as an operator, such as:
int x = 0;
int* y = &x;
*y = 5; // Dereference y pointer, make assignment, in other words, assign to x
You can usually spot a dereference operator because it is not part of a type either in a return type specifier, an argument, or a variable declaration. In most other cases it's the dereference operator.
To my understanding the return type is ' list '(?) which is a structure tag
In your example list is both a struct tag and a typedef name. The name space rules of C allow four different categories of identifiers:
lables (for goto etc)
struct/union/enum tags (struct this_is_a_tag).
struct/union members
everything else
It's valid to name identifiers from these different name spaces the same.
In the example
typedef struct list{ int data; struct list *next;} list;
the typedef list identifier isn't available until at the end of the declaration (after the ;). The struct tag struct list is, however. So the struct list *next; member refers to the struct tag, which is a convenient way create a self-referencing struct. Once the typedef is declared, we can either use list to refer to the typedef:ed struct type, or we can use struct list which means the very same thing - when used outside the struct declaration it's just a style preference which form to use.
So list* create_list(int d) is using the typedef list to declare the return type of the function as a pointer to struct, list*. No different from returning any variable by value vs returning a pointer to it.
In this case the function is calling malloc to create a struct variable, so the function needs to return a pointer because anything allocated by malloc is always accessed through pointers.
Here is the code
struct stack {
int item;
struct stack *next=NULL;
};
I want to make the pointer initially point to null but this shows error
error:expected ':' , ',' , ';' , '}' or 'attribute' before'=' token
The fragment posted does not define an object, it defines a type.
In C you cannot specify the default value of a member in a type definition. You can specify the values of members in an initializer:
struct stack {
int item;
struct stack *next;
};
struct stack my_stack = { 0, NULL };
If you omit the last member in the initializer, it will be initialized to the zero of its type, NULL for a pointer:
struct stack my_stack = { 0 }; // my_stack.next is NULL
One creates a variable of that type, then puts initialization values in braces.
struct stack
{
int item;
struct stack *next;
} stackVar = { 0, NULL};
You cannot perform initializations inside of a struct definition. You can initialize a stack as such:
struct stack {
int item;
struct stack* next;
};
int main(){
struct stack s = {0,NULL};
}
You cannot ask your struct type to set that pointer to null by itself. You will have to do it explicitly every time you create an object of type struct stack, e.g.
struct stack my_stack = { .next = NULL };
or
struct stack my_stack = { 0 };
Both variants have the same effect - they set to zero all fields of my_stack.
If you create your struct stack objects in dynamic memory, then initialization syntax is out of question. You will have to explicitly assign the initial value to your freshly created object, e.g.
struct stack *my_stack = malloc(sizeof *my_stack);
my_stack->next = NULL;
or
struct stack *my_stack = malloc(sizeof *my_stack);
*my_stack = (struct stack) { 0 };
// or
*my_stack = (struct stack) { .next = NULL };
i dont know why the list returned is NULL, this is the code:
In my List.h
struct nodo_ {
char* dato;
struct nodo_ *next;
};
struct nodo_ *Lista;
/*Def list */
void createList(struct nodo_ **Lista);
in my main.c
struct nodo_ *Lista;
int main(){
createList(Lista);
while(Lista != NULL){
printf("The date is %s\n ",Lista->dato); //Error here now
Lisa = Lista->next;
}
return 0 ;
}
in my List.c im create the List :
void createList(struct nodo_ *Lista){
struct nodo_ *Aux_List = list_D;
aux_List = malloc(sizeof(struct nodo_));
char* path_a = "Hello";
char* path_B = "Minasan";
/* Store */
aux_List->dato = path_a;
aux_List = Aux_List->next;
aux_List = malloc(sizeof(struct nodo_));
aux_List->dato = path_b;
aux_List->next = NULL;
}
Thanks.
That pointer is being passed by value, i.e., a copy is made. If you wish to initialize the pointer to a completely new value then you must use another level of indirection (i.e., a nodo_**).
On a side note, typedefing pointer types is almost always a bad idea unless the type is truly opaque (which yours is not). One reason for this "rule" is evident when you consider another bug in your code:
auxList = (Lista*)malloc(sizeof(Lista));
You're allocating space for a pointer to noda_, not enough for a noda_ object. Also, don't cast the return value of malloc in C. It is redundant as a void* is safely and implicitly converted to any other pointer type and, if you forget to include stdlib.h, malloc will be assumed to be a function which returns int, and the cast hides the error. (only applies to compilers which implement C89 or an older version)
EDIT:
To initialize a pointer argument within a function:
void init(struct node **n) {
if(n)
*n = malloc(sizeof(struct node));
}
int main() {
struct node *n;
init(&n);
}
Short answer to your actual question before I dig into the code:
... why the list returned is NULL ...
There is no returned list, you neither use return to pass a result, nor set the value of an out parameter.
In your edited code:
void createList(struct nodo_ **Lista){
struct nodo_ *Aux_List = list_D;
aux_List = malloc(sizeof(struct nodo_));
you first set Aux_List to the current value of Lista, which you know isn't initialized yet, because you're trying to initialize it. Then you discard that value, overwriting aux_List with a new address returned by malloc. You never store anything into *Lista, which would be the only way for this function to work as declared.
As Ed suggests, your typedef is hiding lots of useful information from you, so let's expand it out
struct nodo {
char* dato;
struct nodo *next;
};
/*Def list */
void createList(struct nodo* list_D);
Now, you can see this createList is wrong: you can pass in the head node of a list (which is no use to it anyway), but there is no way for it to return a newly-allocated list to the caller.
Frankly your createList isn't a useful primitive anyway, so I'm going to start with a sensible foundation first:
struct nodo *alloc_nodo(char *dato, struct nodo *next)
{
struct nodo *n = malloc(sizeof(*n));
n->dato = dato;
n->next = next;
return n;
}
Now, before we re-write your createList using this, let's see what it does now:
void createList(struct nodo *list_D)
{
struct nodo *aux_List = list_D;
aux_List = malloc(sizeof(struct nodo_));
/* ^ so, we take the input argument and immediately discard it */
char* path_a = "Hello";
char* path_B = "Minasan";
/* Store */
aux_List->dato = path_a;
aux_List = Aux_List->next;
/* ^ note that we haven't initialized aux_List->next yet,
so this is a random pointer value */
aux_List = malloc(sizeof(struct nodo_));
/* again, we set aux_List to something,
but immediately overwrite and discard it */
aux_List->dato = path_b;
aux_List->next = NULL;
}
So, it ignores its input, returns no output, and leaks two partially-initialized nodes which aren't connected to each other. I believe you wanted to achieve something more like this:
struct nodo* create_my_list()
{
struct nodo *tail = alloc_nodo("Minasan", NULL);
/* the end (tail) of the linked list has a NULL next pointer */
struct nodo *head = alloc_nodo("Hello", tail);
/* the head of the linked list points to the next node */
return head;
/* like a snake, you hold a singly-linked list by the head */
}
If we write main to use this function now, it looks like:
int main()
{
struct nodo *head = create_my_list();
struct nodo *n;
for (n = head; n != NULL; n = n->next)
{
printf("The date is %s\n ", n->dato);
}
}
I'm making a trie and I need someone to tell me what's wrong with this code:
typedef struct node
{
struct node *letters[26]={0};
} node;
I want to make it so that in every reference of a node struct, the pointers are all null...
Your help would be greatly appreciated :) Thanks
You can't initialize a type. You can only initialize objects
typedef struct node {
struct node *letters[26];
} node;
node mynode = {0}; /* {{0}} or even {{0, 0, 0, 0, ...}} */
you could go with the simple approach.
You can create an function,which will create and initialize all pointer with NULL then return node object.
Could be as below.
Node* GetMeANode()
{
//Create an object of Node structure here.
//initialize all pointer with `NULL`
// Return it.
}
You cannot initialize members of structs like that, but you can initialize them at instantiation time, or write an initializing function:
#include <string.h>
typedef struct node
{
struct node *letters[26];
} node;
void initNode(node * n) { memset(n->letters, 0, 26 * sizeof(node *)); }
void foo()
{
/* aggregate initialization, efficient */
node n = { 0, 0, 0, /* 26 times */ };
/* helper function */
node m;
initNode(&m);
}
(If this were C++0x, you could initialize struct members in the default constructor's base initializer list, even arrays.)