I am storing my information in an array of pointers to structs. In other words, each element of the array is a pointer to a linked list.
I don't know how long the array should be, so instead of initializing the array in my main() function, I instead intialize the double pointer
struct graph** graph_array;
Then once I obtain the length of the array, I try to initialize each element of graph_array using a function GraphInitialize:
int GraphInitialize(struct graph* *graph_array,int vertices)
{
struct graph* graph_array2[vertices+1];
graph_array = graph_array2;
int i;
for (i=0;i<vertices+1;i++)
{
graph_array[i] = NULL;
}
return 0;
}
But for some reason this is not returning the updated graph_array to main(). Basically, this function is updating graph_array locally, and no change is being made. As a result, any time I try to access an element of graph_array it seg faults because it is not initialized. What am I doing wrong?
Edit: Following the convo with Tom Ahh I should add something else that makes this more confusing.
I don't call GraphIntialize directly from main(). Instead, I call getdata() from main, and pass a pointer to graph_array to getdata as shown below.
getdata(argc, argv, vertpt, edgept, &graph_array)
int getdata(int argc, char *argv[], int *verts, int *edges, struct graph* **graph_array)
Then getdata gets the number of vertices from my input file, and uses that to call GraphInitialize:
if ((GraphInitialize(&graph_array, *verts)) == -1)
{
printf("GraphCreate failed");
return 0;
}
This results in an error: "expected 'struct graph 3ASTERISKS' but argument is of type 'struct graph 4ASTERISKS'.
When you assign something to graph_array, you simply assign it to its local copy. The changes made to it in the function will not be see-able by the caller. You need to pass it by pointer value to be able to change its value. Change your function prototype to int GraphInitialize(struct graph ***graph_array,int vertices) and when you call it, use GraphInitialize(&graph_array, 42).
Second problem in your code is when you create graph_array2, you declare it to be local to your GraphInitialize() function. Thus, when exiting your function, graph_array2 is destroyed, even if you assigned it to *graph_array. (the star dereferences the pointer to assign it to the value it points to).
change your assignation to *graph_array = malloc(sizeof(*graph_array) * vertices); and you should be fine.
Memory is divided into two parts, the stack and the heap. Malloc will give you back a chunk of memory from the heap, which lives on between functions, but must be freed. Thus your program must be careful to keep track of the malloced() memory and call free() on it.
Declaring a variable graph_array2[vertices+1] allocates a local variable on the stack. When the function returns the stack pointer is popped "freeing" the memory allocated in the function call. You don't have to manage the memory manually, but when the function call is over it no longer exists.
See here for some discussion of the two allocation styles:
http://www.ucosoft.com/stack-vs-heap.html
You're using C99-style local array allocation. The array disappears when the function returns. Instead you need to use malloc() to allocate memory that will persist after the function. You can use typedefs to make your code more readable:
typedef struct graph_node_s { // linked list nodes
struct graph_node_s *next;
...
} GRAPH_NODE;
typedef GRAPH_NODE *NODE_REF; // reference to node
typedef NODE_REF *GRAPH; // var length array of reference to node
GRAPH AllocateGraph(int n_vertices)
{
int i;
GRAPH g;
g = malloc(n_vertices * sizeof(NODE_REF));
if (!g)
return NULL;
for (i = 0; i < n_vertices; i++)
g[i] = NULL;
return g;
}
You have two problems.
First, graph_array2 has auto extent, meaning that it only exists within its enclosing scope, which is the body of the GraphInitialize function; once the function exits, that memory is released, and graph_array is no longer pointing anywhere meaningful.
Second, any changes to the parameter graph_array are local to the function; the changes won't be reflected in the caller. Remember, all parameters are passed by value; if you pass a pointer to a function, and you want the value of the pointer to be modified by the function, you must pass a pointer to the pointer, like so:
void foo(int **p)
{
*p = some_new_pointer_value();
return;
}
int main(void)
{
int *ptr = NULL;
foo(&ptr);
...
}
If you intend for InitializeGraph to allocate the memory for your array, you'll need to do something like this:
int InitializeGraph(struct graph ***graph_array, int vertices)
{
*graph_array = malloc(sizeof **graph_array * vertices);
if (*graph_array)
{
int i;
for (i = 0; i < vertices; i++)
{
(*graph_array}[i] = NULL; // parentheses matter here!
}
}
else
{
return -1;
}
return 0;
}
int main(void)
{
int v;
struct graph **arr;
...
if (GraphInitialize(&arr, v) == 0)
{
// array has been allocated and initialized.
}
...
}
Postfix operators like [] have higher precedence than unary operators like *, so the expression *arr[i] is interpreted as *(arr[i]); we're dereferencing the i'th element of the array. In GraphInitialize, we need to dereference graph_array before subscripting (graph_array isn't an array, it points to an array), so we need to write (*graph_array)[i].
Related
I have a problem using dynamic memory in C.
I am creating a struct whose data is a number and a pointer to another struct (in short, an array of struct). The goal is for the parent struct to store an array of another struct using dynamic memory.
The problem I have is to access the cells of the created array, because I don't know if it's due to syntax issues (I'm new to C), or that I'm creating the array wrong, I can't modify the information contained in each cell of the contained array inside the parent struct. I can only modify by default the first cell.
This is my code, any idea or suggestion will be appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char string[64];
void* date;
void* colour;
} DataState;
typedef struct {
int number;
DataState* array;
} Book;
Book* makeBook (int number){
int a=5;
void* auxiliary=&a;
Book* book_A=(Book*)(malloc(sizeof(Book)));
book_A->number=number;
book_A->array=(DataState*)(malloc(number*sizeof(DataState))); //creating array of structs inside main struct.
//And what I want to do is something like this, modify the information contained in cells of the array of structs of the main struct.
book_A->array[3]->date=auxiliary;
return book_A;
}
From already thank you very much.
Here:
book_A->array[3]->date=auxiliary;
you assign a value of auxiliary to the 3rd element of an array, but auxiliary is defined as
void* auxiliary=&a;
while a is an automatic variable in your function.
Automatic variables disappear at the return from the function, hence the pointer assigned to book_A->array[3]->date becomes invalid as soon as the return is executed.
If you want the data saved in a to remain valid after makeBook returns, then you must allocate it in more persistent storage than automatic. You've essentially done this:
int* foo()
{
int a = 5;
// WRONG, cannot return the address of a local variable
return &a;
}
int main(void)
{
int* a_addr = foo();
// WRONG, invokes undefined behavior
printf("a = %d\n", *a_addr);
}
If you want a to persist outside of foo, a possible option is:
int* foo()
{
int* a = malloc(sizeof *a);
// always check the return value of malloc
if (a != NULL)
{
*a = 5;
}
// this is ok. `a` is still in automatic storage, but this _returns_ its
// value, which is a pointer to data _not_ in automatic storage.
return a;
}
int main(void)
{
int* a_addr = foo();
// still must check here, malloc in `foo` could have failed. Probably
// better to design an architecture where you only check validity once
if (a_addr != NULL)
{
printf("a = %d\n", *a_addr); // prints a = 5
// don't forget to `free(a_addr)` when you're done with it, or you can
// let the OS clean up the memory when the process exits.
}
else
{
// handle error how you want
fprintf(stderr, "Out of mem!\n");
}
return 0;
}
#include<stdio.h>
typedef struct data
{
int a;
int b;
}dd;
dd *changed(dd **d);
dd changep(dd *d);
int main()
{
dd *d=(dd *)malloc(sizeof(*d));
d->a=5;
d->b=6;
changep(d);
printf("after entering into the functin %d\n",d->a);
changed(&d);
printf("%d\n",d->a);
}
dd changep(dd *d)
{
//d=(dd *)malloc(sizeof(*d));
d->a=14;
printf("%d\n",d->a);
}
dd *changed( dd **d)
{
*d=(dd *)malloc(sizeof(*d));
(*d)->a=3;
(*d)->b=4;
}
here changed and changep are changing the values in the structure why 2 use a double pointer then ??
and if i create new memory in changep then it is not changing its value why??
C uses pass by value in function parameter passing.
void changep(dd *pd) //notice the change
{
//d=malloc(sizeof(*d)); //do not cast
pd->a=14;
printf("%d\n",pd->a);
}
and it is called as
changep(d);
Here, pd is local to the function changep, i.e., a local copy of d. Any chnages made to pd will not be reflected to the caller function.
To make the changes relect to the caller [main()], you need a double pointer. That is why
void changed( dd ** pd)
{
if (pd)
{
if (! *pd)
*pd=malloc(sizeof(*d)); //do not cast
(*pd)->a=3;
(*pd)->b=4;
}
}
and the calling
changed(&d);
reflects the changes made to *pd to d in main().
this is difference of function using value parameters and function using reference parameters.
If you want to change a var pointed by a pointer by calling function, you must use a pointer as parameter. So if you want to change a pointer by calling function, you must use a pointer which point to that pointer!
Both of your functions change the values of the struct members. You confusion is over why single or double pointers? and when to use one vs the other? They are effectively the same, but there are a couple of subtle consideration. In both you are passing a pointer (a reference), so the function will receive an address as an argument, and can modify the value stored at that memory address such that the change is visible outside of the function in say main.
First, when passing a single pointer to a struct (or anything else), the intent is generally, not always, but generally to operate on that pointer and memory location such that the caller receives the new values without needing a return. In this general case, there is no general need to return anything, and the function can properly be of type void and return no value.
The second situation is where you need the function to be able to change the address for the data struct in some way, like when deleting a first or last node in a linked-list. In this situation, the function needs to have access to the address of the pointer (not just the memory address the pointer points to) in order to make the node changes.
Here, you generally think of passing the pointer as a double pointer so if a new list node takes its place, not only are the values pointed to by the pointer subject to change, but the address of the pointer itself may undergo a change. This is one of the few areas when passing a double pointer is required -- when you need to change the address of the pointer itself. Since you need to return this pointer to the caller, these functions are generally of the struct pointer type so that after the list address have all gone through their change, you can return the new address to the start of the list (or whatever) to the caller. So these type function are declared as struct name* to accommodate the requirement.
NOTE However, you can still operate on the values of the pointers provided to the function without providing a return, but if you do need to change the address of the struct provided, then the double pointer is required.
Your code acted appropriately with both, and for your double-pointer function, there was no need for a return. but the values in main reflected the new values:
#include <stdio.h>
#include <stdlib.h>
typedef struct data {
int a;
int b;
} dd;
dd *changed (dd ** d);
void changep (dd * d);
int main () {
dd *d = malloc (sizeof (*d));
d->a = 5;
d->b = 6;
changep (d);
printf ("after entering into the functin %d\n", d->a);
changed (&d);
printf ("%d\n", d->a);
return 0;
}
void changep (dd * d)
{
//d=(dd *)malloc(sizeof(*d));
d->a = 14;
printf ("%d\n", d->a);
}
dd *changed (dd ** d)
{
// *d = (dd *) malloc (sizeof (*d));
(*d)->a = 3;
(*d)->b = 4;
return *d;
}
output:
$./bin/spassvr
14
after entering into the functin 14
3
I have an assignment in C to implement a abstract data type STACK. The nature of the data type requires key structure that needs to have memory allocated. My problem is that my instructor insists, for now, for the initialization function to take in a pointer to the key structure. The init() function will do nothing more than allocate the memory necessary for the structure and set a field to zero, but the pointer that is passed in needs to be assigned that memory location.
I can't think of a way to do this without either having the function return a pointer, or to pass in a 2-star pointer - both of which are not allowed. I know The function prototype must be (where stackT* is a pointer to the key STACK data structure):
void init(stackT* stack);
I came up with this and it works fine:
void init(stackT** stack){
*stack = (stackT*) malloc(sizeof(stack));
(*stack)->count = 0;
return;
}
But it does not abide by the restrictions of the assignment.
tl;dr version:
Basically, how can I pass in the address of my original pointer to the STACK data structure (&stackPtr) into a function that takes one-star pointers as arguments and not get a pointer-type warning? Further, once you change the arguments to (stackT* stack) the below code does not work, even though I am passing the same thing either way - this is where my problem is.
I thought it is REQUIRED to have the argument as a 2-star pointer if you intend to pass in a pointer to a pointer .. the compiler must know what it is dealing with when you dereference a pointer.
At any rate, I am not sure how to do this given the restrictions. In my opinion this is only making it unnecessarily more difficult.
I believe, as pointed out in a comment, that you're missing the intention.
I think the idea is that the "root" stackT instance should be a well-known structure, so that you can declare one locally. Then you call init() to set up the actual stack described by the stackT instance:
int push_four(void)
{
stackT my_stack;
init(&my_stack);
push(&my_stack, 1);
push(&my_stack, 2);
push(&my_stack, 3);
push(&my_stack, 4);
}
The above assumes that the stack stores integers, i.e. the allocation inside init() should be something like:
void init(stackT *stack)
{
stack->items = malloc(64 * sizeof *items);
stack->count = 0;
}
And this, in turn, assumes a declaration like:
typedef struct {
int *items;
size_t count;
} stackT;
Of course, the default maximum depth (64) should be a parameter to init(), you must check (but not cast!) the return value of malloc(), and so on.
Typically when you have complex structures then there is a control struct and that one will have a pointer to the real memory.
Example:
struct stack_control_s {
void * memory;
size_t memory_size;
size_t current_size;
};
Then you would pass a pointer to the control structure to your initialiser and make it do the real work;
#define STACK_MIN_SIZE 0x100
int stack_init(struct stack_control_s * stack) {
memset(stack, 0, sizeof(*stack));
stack->memory = calloc(STACK_MIN_SIZE, 1);
if (!stack->memory)
return -1; //error
stack->memory_size = STACK_MIN_SIZE;
return 0; // all good
}
Here is a slightly modified header for a generic C list that I once made. I have added to macros to make it useable as a stack. Maybe this will give you some inspirations:
list_t.h
Use:
list_t(char) mylist;
list_init(&mylist);
list_push(&mylist, 'A');
printf("%c\n", list_pop(&mylist));
Probably it is not the best solution, but you can define your stack globally.
In this case it will look like a:
stackT G_stack;
....
void init(stackT* stack){
stack->count = 0;
return;
}
int main() {
.....
init(&G_stack);
.....
}
In this case you don't need to change prototype.
This assignes the pointer the address of the definition of STACK and passes the pointer to be initialized (using a single * :)... Will this work for you?
#include <ansi_c.h>
typedef struct {
int count;
} COUNT;
typedef struct {
COUNT count;
int *element1;
int *element2;
int address;
} STACK;
STACK stack, *pStack;
void InitStack(STACK *iS);
int main(void)
{ //This is how I think you will meet the
//criteria you are talking about (single *)
pStack = &stack; //assigning address of stack to pointer
InitStack(pStack);
//pStack->address == pStack
return 0;
}
void InitStack(STACK *iS)
{
iS->count.count = 0;
iS->address = (int)iS; //assigning address of stack to member of struct
iS->element1 = calloc(10, sizeof(int));
iS->element2 = calloc(10, sizeof(int));
}
I am storing my information in an array of pointers to structs. In other words, each element of the array is a pointer to a linked list.
I don't know how long the array should be, so instead of initializing the array in my main() function, I instead intialize the double pointer
struct graph** graph_array;
Then once I obtain the length of the array, I try to initialize each element of graph_array using a function GraphInitialize:
int GraphInitialize(struct graph ***graph_array, int vertices)
{
*graph_array = malloc(sizeof **graph_array * vertices);
if (*graph_array)
{
int i;
for (i = 0; i < vertices; i++)
{
(*graph_array)[i] = NULL; // parentheses matter here!
}
}
else
{
return -1;
}
return 0;
}
But here's the problem: I don't call GraphIntialize directly from main(). Instead, I first call getdata() from main, and pass a pointer to graph_array to getdata as shown below.
getdata(argc, argv, vertpt, edgept, &graph_array)
int getdata(int argc, char *argv[], int *verts, int *edges, struct graph* **graph_array)
Then getdata retrieves the number of vertices from my input file, and uses that to call GraphInitialize:
if ((GraphInitialize(&graph_array, *verts)) == -1)
{
printf("GraphCreate failed");
return 0;
}
This results in an error: "expected 'struct graph 3ASTERISKS (triple pointer)' but argument is of type 'struct graph 4ASTERISKS (quadruple pointer)'. This is so confusing. If there is a way I can work this out without needing all these pointers that might be the best answer, but I am trying to create and abstract data type and so I don't want to be creating a graph_array array in my main function.
I suppose, you don't have to use '&' here:
if ((GraphInitialize(&graph_array, *verts)) == -1)
You want to initialize a double pointer (graph**), but to do that you pass a pointer to it into your functions, so both of them get a triple pointer (graph ***) as an input.
The chain of calls looks something like this (this is more of a pseudocode):
void GraphInitialize(struct graph *** graph_array);
void getdata(..., struct graph *** graph_array )
{
...
GraphInitialize(graph_array); //graph_array here is the same triple pointer, that 'getdata' recieved as an input, so there is no need to use '&' operator.
...
}
void main()
{
graph ** graph_array = ...; // this is a double pointer, obviously
getdata( ..., &graph_array); //getdata gets a triple pointer as an input, so we get the graph_array address by '&' operator;
}
So the correct form would be
if ((GraphInitialize(graph_array, *verts)) == -1)
use
if ((GraphInitialize(graph_array, *verts)) == -1)
{
printf("GraphCreate failed");
return 0;
}
this works i hope..
I've just started to work with C, and never had to deal with pointers in previous languages I used, so I was wondering what method is better if just modifying a string.
pointerstring vs normal.
Also if you want to provide more information about when to use pointers that would be great. I was shocked when I found out that the function "normal" would even modify the string passed, and update in the main function without a return value.
#include <stdio.h>
void pointerstring(char *s);
void normal(char s[]);
int main() {
char string[20];
pointerstring(string);
printf("\nPointer: %s\n",string);
normal(string);
printf("Normal: %s\n",string);
}
void pointerstring(char *s) {
sprintf(s,"Hello");
}
void normal(char s[]) {
sprintf(s,"World");
}
Output:
Pointer: Hello
Normal: World
In a function declaration, char [] and char * are equivalent. Function parameters with outer-level array type are transformed to the equivalent pointer type; this affects calling code and the function body itself.
Because of this, it's better to use the char * syntax as otherwise you could be confused and attempt e.g. to take the sizeof of an outer-level fixed-length array type parameter:
void foo(char s[10]) {
printf("%z\n", sizeof(s)); // prints 4 (or 8), not 10
}
When you pass a parameter declared as a pointer to a function (and the pointer parameter is not declared const), you are explicitly giving the function permission to modify the object or array the pointer points to.
One of the problems in C is that arrays are second-class citizens. In almost all useful circumstances, among them when passing them to a function, arrays decay to pointers (thereby losing their size information).
Therefore, it makes no difference whether you take an array as T* arg or T arg[] — the latter is a mere synonym for the former. Both are pointers to the first character of the string variable defined in main(), so both have access to the original data and can modify it.
Note: C always passes arguments per copy. This is also true in this case. However, when you pass a pointer (or an array decaying to a pointer), what is copied is the address, so that the object referred to is accessible through two different copies of its address.
With pointer Vs Without pointer
1) We can directly pass a local variable reference(address) to the new function to process and update the values, instead of sending the values to the function and returning the values from the function.
With pointers
...
int a = 10;
func(&a);
...
void func(int *x);
{
//do something with the value *x(10)
*x = 5;
}
Without pointers
...
int a = 10;
a = func(a);
...
int func(int x);
{
//do something with the value x(10)
x = 5;
return x;
}
2) Global or static variable has life time scope and local variable has scope only to a function. If we want to create a user defined scope variable means pointer is requried. That means if we want to create a variable which should have scope in some n number of functions means, create a dynamic memory for that variable in first function and pass it to all the function, finally free the memory in nth function.
3) If we want to keep member function also in sturucture along with member variables then we can go for function pointers.
struct data;
struct data
{
int no1, no2, ans;
void (*pfAdd)(struct data*);
void (*pfSub)(struct data*);
void (*pfMul)(struct data*);
void (*pfDiv)(struct data*);
};
void add(struct data* x)
{
x.ans = x.no1, x.no2;
}
...
struct data a;
a.no1 = 10;
a.no1 = 5;
a.pfAdd = add;
...
a.pfAdd(&a);
printf("Addition is %d\n", a.ans);
...
4) Consider a structure data which size s is very big. If we want to send a variable of this structure to another function better to send as reference. Because this will reduce the activation record(in stack) size created for the new function.
With Pointers - It will requires only 4bytes (in 32 bit m/c) or 8 bytes (in 64 bit m/c) in activation record(in stack) of function func
...
struct data a;
func(&a);
...
Without Pointers - It will requires s bytes in activation record(in stack) of function func. Conside the s is sizeof(struct data) which is very big value.
...
struct data a;
func(a);
...
5) We can change a value of a constant variable with pointers.
...
const int a = 10;
int *p = NULL;
p = (int *)&a;
*p = 5;
printf("%d", a); //This will print 5
...
in addition to the other answers, my comment about "string"-manipulating functions (string = zero terminated char array): always return the string parameter as a return value.
So you can use the function procedural or functional, like in printf("Dear %s, ", normal(buf));