#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
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.
I am not great on pointers but I have to learn in the field. If my understanding serves me correct these should all be valid statements below.
int* a;
int b = 10;
a = &b;
(*a) = 20;
(*a) == b; //this should be true
if you have a function like this:
void copy(int* out, int in) {
*out = in;
}
int m_out, m_in;
copy(&m_out, m_in);
m_out == m_in; // this should also be true
but I saw a function like this
create(float& tp, void* form, char* title);
I understand the void pointer, it can be cast to anything, I understand the character pointer which is basically a c style string.
I do not understand the first argument, which is the address of some type, let's say a float but it could be anything, a struct, a int, etc.
What is going on there?
First this
int m_out, m_in;
copy(&m_out, m_in);
is undefined behaviour - you passed uninitialized vaiable m_in to function - and hence trying to make copy of an uninitialized variable.
This:
create(float& tp, void* form, char* title);
doesn't make sense in C. Looks like reference from C++.
The first argument is a reference, it just means that if you modify this field in your function create, the field will still remain modified (even in the function where you called create()) because it points to an address and not a value.
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));
I know why this works:
#include <stdio.h>
void cool_number(int **number) {
int value = 42;
int *p = &value;
*number = p;
}
int main () {
int *number;
cool_number(&number);
printf("number is %d\n", *number);
return 0;
}
What I don't understand is why this doesn't (in my machine it prints 3700 or something like that).
#include <stdio.h>
void cool_number(int **number) {
int value = 42;
int *p = &value;
int **x = &p;
number = x;
}
int main () {
int *number;
cool_number(&number);
printf("number is %d\n", *number);
return 0;
}
Why aren't both equivalent?
both are evil as they capture the address of a stack variable.
Second one doesn't do what you expect because you are assigning directly to the parameter number, which is only temporary, the first one changes something the parameter number pointers to, which is the same thing as number in main points to.
I assume they're not equivalent because number is passed by value, on the stack, as is standard for function parameters. Any changes that you make directly to number inside of cool_number() are modifying the local copy on the stack, and are not reflected in the value of number in main().
You get around this in the first example by dereferencing number, which tells the computer to modify some specific location in memory that you also happen to have a pointer to back in main(). You don't have this in the second example, so all that happens is that you make the local number pointer point to somewhere else, without actually updating any memory location being referred to back in main(). Thus nothing you do shows up once you get back to main().
And since value is local to the cool_number() function, setting a reference to it that will be accessed after cool_number() returns isn't guaranteed to work and certainly shouldn't be used in any code outside of a trivial/toy example. But in this specific instance it's not really related to why you're seeing different results between the two pieces of code.
As I understand, in both cases, your code is wrong.
In the first case, you are returning an address to a variable allocated on stack, which will be deallocated as soon as the function returns.
In the second case, the error of the first case exists, plus you are passing number by value, so an updation to number will not get reflected in the caller function.
In 'C', arguments are always passed by value. So, you cannot update the argument passed as it is. For Ex:
int func(int a)
{
a = 5; // In this case the value 5 will not be reflected in the caller as what is updated is the local copy of a on the stack
}
int func(int *a)
{
*a = 5; // This update will show in caller as you are directly updating the memory pointed to by a
a = malloc(4); //This update will not show in caller as again you are updating the local copy of stack
}
#include <stdio.h>
void cool_number(int **number) {
int value = 42; /* this "value" hold 42 value,
and it lifetime is only in this function */
int *p = &value; /* here we get the address of "value" in memory */
*number = p;
}
int main () {
int *number;
cool_number(&number); /* after this function the "value" in memory had been recyled
and may be used by other program */
printf("number is %d\n", *number); /* so when we print value here it will be
a unpredictable value, somehow may be crash */
return 0;
}
both the same principle