Scope and Linked Lists in C - c

I'm trying to get more comfortable building and using linked lists in C, and for the most part I think I have the basics down. However, I am running into problems in regards to Scope, specifically the linkage of a Pointer to a Pointer of structs.
In my linked_list.c implementation I am using a main function to test out and play around with the linked list functions I've built. But the eventual goal is to run Main from another file, and only reference the few functions I'd need externally from a header file.
The implementation I'm using right now DOES work, but it seems to rely on me declaring the struct list** inside my (temporary)) main function.
It's my understanding that if you declare a variable/pointer outside of a block, you can control the linkage to be internal, accessible to other functions in the file, using the static command. What I would like to be able to do is call a function like void initialize_list() from OUTSIDE the program and have it initialize this internally linked list**.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
int value;
struct node *next;
};
struct list {
struct node *head;
struct node *tail;
int size; // Maintains current size of list
};
static struct list** work_list;
void dirty_init(void){
struct list* new_list = malloc(sizeof(struct list));
new_list->head = NULL;
new_list->tail = NULL;
new_list->size = 0;
*work_list = new_list;
}
Running my dirty_init function returns a segfault.
The version of code that DOES work is quite similar, but it seems to rely on the **work_list being declared inside of my main function before passing it to initialize_list.
void initialize_list(struct list **out_list){
struct list* my_list = malloc(sizeof(struct list));
my_list->head = NULL;
my_list->tail = NULL;
my_list->size = 0;
*out_list = my_list;
}
int main(void){
int i;
struct list **work_list;
initialize_list(work_list);
}
This is all well and good, but it has the drawback of making my **work_list pointer internally linked to the Main block. Any ideas where I am going wrong trying to get the dirty_init function to work?

This here:
int main(void){
int i;
struct list **work_list;
initialize_list(work_list);
}
can't work. C is pass by value and you pass an uninitialized value, which is then used as a result pointer. Did you mean
int main(void){
int i;
struct list *work_list;
initialize_list(&work_list);
}
instead?

Related

C structure containing references to another structure

I'm learning C and trying to create dynamic double ended queue. I need to have one structure element that contains references to queue's front and end (head, tail of type node) and I'm trying to pass this element to a function and allocate memory for head and tail node. And i get segmentation fault.
My structures
struct node_st {
struct node_st* prev_node;
struct node_st* next_node;
// Value type can be changed.
int value;
bool is_zero_element;
};
typedef struct node_st node;
struct deque_link {
struct node_st* head;
struct node_st* tail;
int errorcode;
};
typedef struct deque_link dlink;
Main function
#include "deque.h"
#include <stdio.h>
int main() {
dlink* deque;
deque_create(deque);
}
deque_create() function
void deque_create(dlink* deque) {
deque->head = deque->tail = (node*)malloc(sizeof(node));
}
I guess I don't understand pointers enough, but I will be very happy if someone could help.
The pointer deque that you pass to deque_create is not initialized. It has indeterminate ("garbage") content. Therefore, it does not point to a valid deque. But you try to access it with the -> operator.
Your initialization / creation of the deque is on the wrong level: You try to create nodes, but you should create a deque (without any nodes, initally.)
You could write a constructor function that allocates memory and initializes it:
dlink *deque_create(void)
{
dlink *deque = malloc(sizeof(*deque));
// Handle allocation failure
deque->head = deque->tail = NULL;
deque->errorcode = 0;
return deque;
}
Then use it like this:
dlink* deque = deque_create();
// do stuff with deque
// delete deque and its nodes
You should also write a destructor function which deletes all nodes to complement the constructor.

C Programming EXC_BAD_ACCESS (code:1 ,address=0x0) Error

Hi guys I'm learning C programming. I wanted to write some codes for learning linked list topic but there is a problem. This code about creating linked list with 5 nodes, writing something into 3rd node, printing them to console.
Here is all of my codes:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
struct node{
char *data;
struct node *next;
};
typedef struct node node;
node *root;
void nodeAdd(node *n, int x)
{
node *iter;
iter=root;
for(int i=0;i<x;i++)
{
iter->next = (node*)malloc(sizeof(node));
iter->next->data="0";
iter->next->next=NULL;
iter=iter->next;
printf("Node created.\n");
}
}
void nodeWrite(node *n,char *string,int x)
{
node *temp;
temp=root;
for(int k=0;k<x;k++)
{
temp=temp->next;
}
strcpy(temp->data,string); //HERE IS ERROR
printf("\n");
printf("%s \n",temp->data);
printf("Node writed.");
}
void nodePrint(node *n)
{
while(root->next!=NULL)
printf("%s\n",root->data);
root=root->next;
}
int main(int argc, const char * argv[])
{
root = (node*)malloc(sizeof(node));
nodeAdd(root,5);
nodeWrite(root,"WTF", 3);
nodePrint(root);
return 0;
}
data is an unintialized pointer variable. Initialize with the address of a valid memory that you allocate. That will solve the problem. Now you have udnefined behavior.
What you can possibly do is
Use char array instead of using pointer.
Allocate dynamically the memory.
In case of 1.
struct node{
char data[MAXSTRINGLEN];
struct node *next;
};
In case of 2:
Initially make the pointers point to NULL. So now you can allocate to it like this
temp->data = malloc(sizeof *temp->data*MAXSTRINGLEN);
if( temp->data == NULL)
{
fprintf(stderr,"Error in malloc");
exit(1);
}
Just one point, free the allocated memory when you are done working with it.
Use of the global variable here is not really required here. You can always pass return pointers from memory and assign it to the struct node*. Or yes you can use double pointers. Use of global variable is not needed here.
Clean up code, that are redundant and not required. That makes things readable and less confusing.
The program initially is designed incorrectly and has undefined behavior..
For example the data member data of the node root was not initialized. So its output in the function nodePrint results in undefined behavior. Moreover the function itself is incorrect.
Neither function uses its parameter node *n.
In this statement
strcpy(temp->data,string);
there is an attempt to change the string literal pointed to by the data member temp->data provided that the data member was initialized (as it was pointed above the data member is not initialized for the node root). You may not change a string literal. Any attempt to modify a string literal leads to undefined behavior.
There is no need to declare the node root as a global variable.
Parameters of the function main are not used in the program. So the function should be declared like
int main( void )

How to make library for linked-list functions

I want to create static or dynamic library for linked list functions, but when I try to compile function files with gcc to get object file it gives me error ‘struct node’ declared inside parameter list
int GetNth(struct node* head, int index) & dereferencing pointer to incomplete type ‘struct node’ if(i == index) return head->data;. Not sure what's going on, may be because I haven't declared the structure in the file
#include <stdlib.h>
int count(struct node* head, int n) //counts the occurrence of n in the list
{
int c = 0;
while(head != NULL){
if(head->data == n) c+=1;
head = head->next;
}
return c;
}
But if I'll declare it inside this file, I think it'll violate 1 definition rule. What to do?
structure is declared in the main function as
struct node{
int data;
struct node *next;
}
Prior to using objects (you use it, when have access to its members) you must completely define them. So, to use struct node, declare it before its first appearance in the source code. It's the rule of C programming language.
Put the declarations into header file and include the file into source files if you want to create useful libraries, e.g.:
...
struct node
{
...
};
int count(struct node *head, int n);
...
Continuing from the comment, in your code, the compiler does not know what node is because you have not provided its declaration. You can provide a declaration including a typedef for convenience. The following code declares a typedef to struct _node {...} as node; and then declares two nodes (statically for simplicity reasons), iterates over the list, outputting the data values and then ends, e.g.
#include <stdio.h>
typedef struct _node {
int data;
struct _node *next;
} node;
int main (void) {
node n1 = {.data = 1},
n2 = {.data = 2, .next = NULL};
n1.next = &n2;
/* iterate over list outputting data values */
for (node *n = &n1; n != NULL; n = n->next)
printf ("%d\n", n->data);
return 0;
}
Example Use/Output
$ ./bin/llstatic
1
2
As mentioned, you can create a header file for your list and include your declaration of struct _node and the typedef there, or if you simply use node within this source-file, you can declare it here. Let me know if you have further questions.
The compiler tells you it does not recognize struct node. You need to Declare it first. Something like struct node; (decleration) or struct node{...}; (definition) and the error should go away. If you have already declared it in another file header.h, just add #include "header.h" in the start of your code
Since you want struct node to contain a field called data, you need to add it when you define the struct:
struct node{
int data;
}

Trying to create an empty linked list in C

I'm trying to create an empty linked list, which asks the user for the maximum number of terms that the list can hold. (I didn't add my code for that as its simply a printf). I then have to create a new function which asks the user to insert input into the previously created list.
My question is, how do I make the create_q() function return the empty list?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node_t {
int value;
int priority;
struct node_t *next;
}node;
typedef struct priority_linked_list {
struct name *head;
int current_size;
int max_size;
}priority_list;
typedef node *Node;
typedef priority_list *List;
void create_q(int max_terms) {
node *head = NULL;
node *next = NULL;
List *current_size = 0;
List *max_size = max_terms;
}
In C, linked lists are usually implemented as a series of nodes stored on the heap that point to eachother. The heap is a persistent memory area that runs throughout the life-cycle of the program.
When you create a variable normally in a C function, and the function returns, the variable that you created is no longer accessible. However when you create something on the heap in a function, and the function is returned, the data you allocated on the heap is still there. However, you have no way of accessing it-- unless the function returns a pointer.
So what you would do for create_q() would be to create the linked list on the heap (using a function in stdlib.h called "malloc"), and then you would return a pointer to your first node, letting the main function know where on the heap to find the first node. Then that first node would have a pointer in it, telling the program where on the heap to find the second node, and so forth.
However, you're probably approaching linked lists the wrong way. Unless this is for some sort of homework project, you probably wouldn't want to create an empty linked list. One of the benefits of a linked list is that it's a dynamic structure in which you can easily insert new nodes. You could still have some variable keeping track of the maximum size you want the list to be, but you probably wouldn't want to actually create the nodes until you had to.
Just keep in mind what a linked list is. It's a set of nodes floating on the heap (in C) that each store some data, and contain a pointer to the next node floating on the heap. All you need, to access the linked list, is a pointer to the first node. To add a new node, you simply "walk" through the list till you reach the last node, and then create a new node and have the old-last node point to it.
Is this what you had in mind?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node_t
{
int value;
int priority;
struct node_t *next;
};
static int current_size;
static int max_size;
static struct node_t* head = NULL;
struct node_t* create_q(int);
struct node_t* create_q(int max_terms)
{
int i; // loop counter/index
current_size = max_terms;
max_size = max_terms;
if( NULL == (head = malloc(sizeof(struct node_t)*max_terms)))
{ // then, malloc failed
perror("malloc failed for struct node_t list");
exit( EXIT_FAILURE );
}
// implied else, malloc successful
// set all fields to '0,0,Null'
memset( head, 0x00, sizeof(struct node_t)*max_terms);
// set all next links, except last link
for(i=0;i<(max_terms-1);i++)
{
head[i].next = &head[i+1];
}
// set last link
head[i].next = NULL;
return( head );
} // end function: create_q
I suspect you are looking for something like the following for creating or initializing your priority linked list.
/*****
* alloc_q - allocate memory for the priority linked list
*/
struct priority_linked_list *alloc_q(void)
{
struct priority_linked_list *list;
list = malloc(sizeof(*list));
return list;
}
/******
* init_q - initialize the priority linked list
*/
void init_q(struct priority_linked_list *list, int max_terms)
{
list->head = NULL;
list->current_size = 0;
list->max_size = max_terms;
}
/******
* create_q - allocate AND initialize the priority linked list
*/
struct priority_linked_list *create_q(int max_terms)
{
struct priority_linked_list *list;
list = alloc_q();
if (list == NULL) {
return NULL;
}
init_q(list, max_terms);
return list;
}
Allocation of nodes and their addition/removal to/from the list would be handled separately.
There may be typos in the above (I have not tested it). However, it should be enough to get you on the path you want.
Hope it helps.

Error while generating an array of pointer

Trying to implement below code for some assignment but getting an error for malloc array generation "[Error] conflicting types for 'stack'" Any Help ??
Thanks in Advance.
#include<stdio.h>
#include<stdlib.h>
struct treenode
{
char info;
struct treenode *firstchild;
struct treenode *next;
int flag;
};
typedef struct treenode *NODEPTR;
NODEPTR *stack;
// Trying to create array here
stack=(NODEPTR*)malloc(sizeof(NODEPTR)*20);
int main()
{
printf("YO\n");
return 0;
}
EDIT :
I can't move it to main , as i have to access the stack globally in different functions.
because Stack array gets destroyed when it go to another function.
check here http://ideone.com/5wpZsp ,
When i give static declaration globally it works smoothly, here : http://ideone.com/3vx9fz
You can not call assignment operations at global scope. Try malloc operation in main() instead.
And the type of stack is not a pointer but pointer to pointer. Are you sure about it's declaration ?
Move your initialization of stack to inside of the main method.
EDIT An example showing how the malloc data can persist to other function calls even though malloc is called inside of main.
#include<stdio.h>
#include<stdlib.h>
struct treenode
{
char info;
struct treenode *firstchild;
struct treenode *next;
int flag;
};
typedef struct treenode *NODEPTR;
NODEPTR *stack;
void test_stack()
{
printf("%p\n", stack);
printf("%d\n", stack[19]->flag);
}
int main()
{
// Trying to create array here
stack=(NODEPTR*)malloc(sizeof(NODEPTR)*20);
stack[19] = (NODEPTR*)malloc(sizeof(struct treenode));
stack[19]->flag = 42;
test_stack();
return 0;
}
Step 1: Move the declaration of stack inside main. There's no reason it should be declared globally:
int main( void )
{
NODEPTR *stack;
...
Step 2: Move the malloc call inside main (you cannot perform an assignment or a function call outside of a function).
Step 3: Drop the cast; it's unnecessary1 and just adds visual clutter.
Step 4: Use sizeof *stack as opposed to sizeof (NODEPTR) in the argument to malloc:
stack = malloc( sizeof *stack * 20 );
The result is the same, but this is easier to read, and avoids maintenance headaches if you ever change the type of stack.
Step 5: free your stack when you're done. Yeah, for this program it doesn't matter, but it's a good habit to get into.
So after all this, your code should read:
int main( void )
{
NODEPTR *stack;
stack = malloc( sizeof *stack * 20 );
...
free( stack );
return 0;
}
Stylistic nit: Hiding pointer types behind typedefs is bad juju IME. Pointer semantics are important, and if the programmer is ever expected to dereference an object of type NODEPTR (either explicitly, as (*node).info, or implicitly, as node->info), then it's usually best to declare that object using pointer declaration syntax, something like
typedef struct treenode Node;
Node *node;
Node **stack;
...
stack[i]->next = node->next;
etc. so the person using your types knows exactly how many levels of indirection are involved and can write their code accordingly (multiple indirection is not hard). If the type is meant to be truly opaque and never directly dereferenced, but just passed around to an API that handles all that, then hiding the pointerness of that type is okay. Otherwise, leave it exposed.
I tend not to typedef struct types for a similar reason, but I suspect I'm an outlier in that regard.
Ahd who broke the code formatter?!
1 - In C, that is; in C++, the cast is required, but if you're writing C++, you should be using new instead of malloc anyway.
#include<stdio.h>
#include<stdlib.h>
struct treenode
{
char info;
struct treenode *firstchild;
struct treenode *next;
int flag;
};
typedef struct treenode *NODEPTR;
NODEPTR *stack;
int main()
{
stack=malloc(sizeof(NODEPTR)*20);
printf("YO\n");
return 0;
}
This will work.
allocate memory inside(malloc) your main.
There is no need to typecast out put of malloc. for further info see this post
EDIT :
In your comment you mentioned that memory will be destroyed when you move other function.
This is not true. Once you allocate memory using malloc it will not be destroyed until you call free().
So if you want to access the malloc'ed variable in other function pass the variable as argument to other function.
See this example program below
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
char *str;
void passMalloc(char **str);
int main()
{
str = malloc(100 * sizeof(char));
strcpy(str, "GoodMorning");
printf("\nMain before pass : %s\n", str);
passMalloc(&str);
printf("Main after pass : %s\n\n", str);
free(str);
return 0;
}
void passMalloc(char **str)
{
strcpy(*str, "GoodEvening");
printf("Function Def : %s\n", *str);
}

Resources