I am trying to define a pointer to a struct as a global variable and access the value of its variables in different functions. But I realized that the values are cleared after the next function call. Am I doing something wrong?
struct St {
double* varDouble;
};
struct St* StGlobal;
void Fun1(){
double initDouble[2][1] = {{1},{2}};
StGlobal = (struct St*)malloc(sizeof(struct St));
StGlobal->varDouble = *initDouble;
};
void Func2(){
for (i =0;i<2;i++){
printf("%d\n", StGlobal->varDouble);
}
};
int main(){
Func1();
Func2(); // value of StGlobal->varDouble is no longer what was assigned to it in Func1
};
void Fun1(){
double initDouble[2][1] = {{1},{2}};
StGlobal = (struct St*)malloc(sizeof(struct St));
// OK. StGlobal points to a memory that was returned by malloc.
// The memory will be valid after the function returns.
StGlobal->varDouble = *initDouble;
// Not OK. initDouble is a local 2D array. *initDouble is a pointer
// that is valid as long as initDouble is in scope. When the function
// returns the pointer is not valid.
};
And
void Func2(){
for (i =0;i<2;i++){
printf("%d\n", StGlobal->varDouble);
// StGlobal->varDouble is dangling pointer.
// Also, you are printing a pointer using %d. ???
// If you try to access the pointer here, the program will exhibit
// undefined behavior since it is a dangling pointer.
}
};
After you allocate memory for StGlobal, you'll have to:
Allocate memory for StGlobal->varDouble also using malloc, or
Assign it to some other pointer that will be valid after the function returns.
Also. Don't cast the return value of malloc in C. See Do I cast the result of malloc?.
Additional info
You can force MSVC to treat a file as a C program file by setting a compiler option. In VS2008, I can do that in the following dialog box.
There is probably a similar way to change the setting in MSVC 2010.
Related
I'd like to ask a simple question. Please, consider the attached code. In the main function, a pointer to a struct is built in two different ways by means of either ctor1 or ctor 2. In both cases the program works no matter which constructor I use.
The reason why ctor1 works is that memory for struct instance is allocated outside the function frame (i.e. in the heap). Therefore, it will be available in the main function after ctor1 termination.
My question boils down to ctor2 function. As far as I know, the local variable "myPtr foo" is expected to be destroyed at the function end. Hence, "that" pointer should point to nothing from now on. Having executed the program however, I found out that both constructors work flawlessly.
Obviously, there is a subtle detail that eludes me. Could you explain why function ctor2 works?
Thank you in advance!
#include <stdio.h>
#include <malloc.h>
int _method(void) {
return 0;
}//_foo
typedef struct vTable {
int (*method)(void);
} myPtr;
myPtr *ctor1(void) {
myPtr *foo;
foo = (myPtr*)malloc(1 * sizeof(myPtr));
foo->method = &_method;
return foo;
}//ctor1
void ctor2(myPtr *that) {
myPtr foo = { &_method };
that = &foo;
return;
// having reached the function end "foo" is destroyed
// and "that" should point to nothing, supposedly
}//ctor2
int dtor(myPtr *foo) {
free(foo);
foo->method = NULL;
foo = NULL;
return 0;
}//dtor
int main(void) {
myPtr *vPtr;
// it works as expected
vPtr = ctor1();
printf("%p\n\n", vPtr); // 003E0F68
dtor(vPtr);
// it works surprisingly enough
ctor2(vPtr);
printf("%p\n", vPtr); // 003E0F68
printf("%p\n", vPtr); // 003E0F68
// it keeps on working
printf("%p\n", vPtr); // 003E0F68
dtor(vPtr);
return 0;
}//main
Screenshot
The code void ctor2(myPtr *that) declares that to be a parameter that points to an object of type myPtr. Parameters are passed by value, so the parameter that is only a copy of whatever was passed. Changing that does not change the thing that was passed.
If you want to change the value of a pointer to myPtr, you must pass a pointer to a pointer to myPtr:
void ctor2(myPtr **that)
Then you can change it with:
*that = malloc(…);
There are several problems here, let's go through them one by one.
First, in your ctor2 function:
void ctor2(myPtr *that) {
myPtr foo = { &_method };
that = &foo;
return;
}//ctor2
This function is actually taking in a pointer to myPtr by value and modifying it locally to point to something allocated on the stack in the function. This has on effect on the pointer passed in. If you wanted to modify the pointer passed in, you would have passed in a double pointer and dereference it:
void ctor2(myPtr **that) {
//malloc foo
*that = foo;
return;
}
Secondly, because you never modified vPtr through the call to ctor2 the second call to dtor is freeing already freed memory, which is undefined behavior that usually leads to a crash. I'm surprised it didn't crash on your system, but that's the thing with UB, you never know.
Thirdly, the behavior you wanted to emulate is:
/* constructor */
void Shape_ctor(Shape * const me, int16_t x, int16_t y) {
static struct ShapeVtbl const vtbl = { /* vtbl of the Shape class */
&Shape_area_,
&Shape_draw_
};
me->vptr = &vtbl; /* "hook" the vptr to the vtbl */
me->x = x;
me->y = y;
}
The difference is that in this case the ShapeVtbl structure is statically allocated. This is OK because it only points to functions, which will not change from object instance to object instance. But having it statically allocated allows it to be allocated within a function like that and assigned to the object.
To amplify Eric Postpischil's excellent answer, consider,
void foo( int i ) { i++; }
This function changes the value it was passed, but not that value is a copy of the original when it was invoked,
int j=8;
foo(j);
You wouldn't expect j to change, right?
The same is true for
void ctor2(myPtr *that) { // my version
that = NULL;
}
that is a copy of the parameter passed on invocation,
ctor2(vPtr);
Because vPtr doesn't change, your program prints ... its unchanged value.
ctor2 can change the value of anything pointed to by that, but any change to the parameter itself has only a local effect.
There are other errors in your program, as other answers point out. But the answer to why ctor2 "works" is basically that it doesn't do anything.
#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)
{
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].
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));