Let's say a have a pointer as a parameter, why doesn't it's value remain modified after the and of a function, and i have to use this syntax :
void function_name (int **p)
{
// code
}
and in main() :
int *v;
function name (&v);
I want to specify that i use a pointer to a struct type as a parameter.
C passes arguments by value. If you want to modify something in a function and make the modification take effect in the calling function, a pointer to the variable in the calling function has to be passed. Otherwise, any changes made to the variable in a function are only local changes and does not affect the value of the variable in the calling function.
Let's start with an int type variable.
void foo(int x)
{
x = 10;
}
int main()
{
int a = 100;
foo(a); // Value of a does not change in this function
}
In the above program, the value of a remains 100 in main. The line
x = 10;
in foo only affects the value of the variable in foo. To make the change in foo affect the value in main, you'll need to pass a pointer to a.
void foo(int* x)
{
*x = 10;
}
int main()
{
int a = 100;
foo(&a); // Value of a changes in this function
}
Take that analogy to a pointer.
void bar(int* x)
{
x = malloc(10*sizeof(int));
}
int main()
{
int* ptr = NULL;
bar(ptr); // Value of ptr does not change in this function
}
bar allocates memory for an array of 10 ints and assigns the memory to x but that change is local. main does not see it. In main, ptr is still NULL. To make the change in bar affect ptr, a pointer to ptr has to be passed to bar.
void bar(int** x)
{
*x = malloc(10*sizeof(int));
}
int main()
{
int* ptr = NULL;
bar(&ptr); // Value of ptr changes in this function
}
In C, arguments are passed by value. This means that when you pass an argument to a function, a copy of that variable is made. For example
int main()
{
int x = 6;
repchar(x, 'r');
printf("%d\n", x);
return 0;
}
void repchar(int n, char c)
{
while (--n >= 0)
putchar(c);
}
This program prints the letter r six times, and then at the last printf, prints out 6, not -1. The reason is that when repchar was called, x was copied. That way, when repchar decrements n, the caller's copy is not changed.
If we passed a pointer, however, n would be modified.
int main()
{
int x = 6;
repchar(&x, 'r');
printf("%d\n", x);
return 0;
}
void repchar(int *n, char c)
{
while (--(*n) >= 0)
putchar(c);
}
Instead of the variable being copied, now the address of the variable is being copied. Inside of repchar, *n is being counted down. This accesses the value that is being referenced by n, which is the same address as x and decrements it. As a result, the last printf will give -1.
Related
I just started learning C language, and I can't fully understand why we should use pointers of pointers in order to append an element into the table (*tab).
here's the code :
#include "append.h"
int append(int ** tab, size_t *size, int value){
int *nouveauTab = realloc(*tab, (*size + 1) * sizeof(int));
if (nouveauTab == NULL){
return 0;
}
*tab = nouveauTab;
(*tab)[*size] = value;
(*size)++;
return 1;
}
If not to use pointer to pointer then the pointer tab will be passed by value. That is the function will deal with a copy of the value of the original pointer. Changing the copy does not influence on the original pointer. It will stay unchanged because it is its copy that was changed within the function.
So you need to pass the pointer by reference.
In C passing by reference means passing an object (a pointer is an object) indirectly through a pointer to it. Thus dereferencing the pointer the function will have a direct access to the original object. In the case of your function to the original pointer like
*tab = nouveauTab;
The short answer is: Because you want to change the value of a pointer in the caller of append. That happens here: *tab = nouveauTab;
The code calling your append function will look something like:
int* table = NULL;
size_t table_size = 0;
if (append(&table, &table_size, 42) == 0)
{
puts("append failed");
}
else
{
printf(size is now %zu and element %zu is %d", table_size, table_size-1, table[table_size-1]);
}
So your code expects that append (on success) will change the value of both table and table_size. That requires that you pass the function pointers to these two variables.
If you did it without usinb pointers, i.e. like:
if (append(table, table_size, 42) == 0)
the function would not be able to change their values as C would just pass a copy of their current values.
A simple example using int
void foo(int x)
{
x = x + 1;
printf("%d\n", x);
}
int x = 42;
printf("%d\n", x);
foo(x);
printf("%d\n", x);
will print
42
43
42 <--- x not changed by `foo` because we passed the value of x (i.e. 42)
but with this:
void foo(int* x)
{
*x = *x + 1;
printf("%d\n", *x);
}
int x = 42;
printf("%d\n", x);
foo(&x);
printf("%d\n", x);
it will print
42
43
43 <--- x was changed by `foo` because we passed a pointer
what should be the output of this code below? and why?
I am not sure if the int i declared in the main function acts like a local variable, or not.
static int i = 3;
void f(int*j){
j++;
}
int g(int* j){
return i+=*j;
}
void h(int j, int k){
printf("%d,%d,%d\n", i,j,k);
}
int main(){
int i = 3;
int j = 5;
int *p = &i;
f(&i);
f(p);
for(;i<5;i++){
*p = g(p);
}
h(i,j);
return 0;
}
These calls of the function f
f(&i);
f(p);
have no effect.
Within the function g there is changed the global variable i
int g(int* j){
return i+=*j;
}
As the function is called in the loop
for(;i<5;i++){
*p = g(p);
}
one time for i equal to 3 then the global variable i will be equal to i + 3 = 6. The local variable i will be equal to the returned value of the global variable i (equal to 6) from the function and then will be incremented in the loop. So after exiting the loop it will be equal to 7..
This call
h(i,j);
outputs the global variable i and passed as arguments the local variables i and j. So its output will be 6,7,5.
int main ()
{
int a, b;
call(&b);
printf("%d, %d",a , b);
}
void call(int *ptr)
{
}
Desired output:
50, 100
How to write the call function so as to modify both the variables to get the desired output??
Not sure where the values 50 and 100 are coming from or exactly what you are asking but maybe this will help with your question.
Since C is pass by value you need to send pointers to actually change the value inside another function.
Since the call function will have pointer values you need to dereference the pointers before changing the value.
Here is an example:
void call(int *a, int *b)
{
*a = 50;
*b = 100;
}
int main()
{
int a, b;
call(&a, &b);
printf("%d, %d\n", a, b);
}
While we are exploring the many ways this output could be achieved, consider that the function could store state in a static variable:
#include <stdio.h>
void call(int *ptr);
int main(void)
{
int a, b;
call(&a);
call(&b);
printf("%d, %d\n",a , b);
}
void call(int *ptr)
{
static int store = 0;
store += 50;
*ptr = store;
}
Program output:
50, 100
Note that you may also be able to do this as follows, without any modifications to main(). But be warned that this method invokes undefined behavior! It is undefined behavior to write to a location past the end of an array object, and in the case of a and b, these are considered to be array objects of size 1. Here we are assuming that this write will work, and that a and b are stored next to each other in memory. We further assume that a has the higher address in memory.
I would say that you should never do this, but I can see no other way to modify a from the function call() without knowing the address of a. You have been warned.
void call(int *ptr)
{
*ptr = 100;
*(ptr + 1) = 50;
}
Try something like this:
void call(int *ptr)
{
*ptr = 100;
}
int main ()
{
int a, b;
a = 50;
call(&b);
printf("%d, %d",a , b);
}
See demo
Maybe you want this:
int main ()
{
int a, b;
call(&a, &b);
printf("%d, %d",a , b);
}
void call(int *ptr1, int *ptr2)
{
*a = 50;
*b = 100;
}
To change a local variable in function a by calling function b you have two options.
1) Let function b return a value that you assign to the variable in function a. Like:
int b() {return 42;}
void a()
{
int x = b();
printf("%d\n", x);
}
This does, however, not seem to be what you are looking for.
2) Pass a pointer to the variable to function b and change the variable through that pointer
void b(int* p) // Notice the * which means the function takes a pointer
// to integer as argument
{
*p = 42; // Notice the * which means that 42 is assigned to the variable
// that p points to
}
void a()
{
int x;
b(&x); // Notice the & which means "address of x" and thereby
// becomes a pointer to the integer x
printf("%d\n", x);
}
int main()
{
int a,b;
call(&b);
printf("%d, %d\n", a,b);
}
int call(int *ptr)
{
int *m;
m = ptr++;
*ptr = 50;
*m = 100;
}
Hi,
I'm a bit new to C's malloc function, but from what I know it should store the value in the heap, so you can reference it with a pointer from outside the original scope. I created a test program that is supposed to do this but I keep getting the value 0, after running the program. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
int f1(int *b) {
b = malloc(sizeof(int));
*b = 5;
}
int main(void) {
int *a;
f1(a);
printf("%d\n", a);
return 0;
}
Yes! a is passed by value so the pointer b in function f1 will be local..
either return b,
int *f1() {
int * b = malloc(sizeof(int));
*b = 5;
return b;
}
int main() {
int * a;
a = f1();
printf("%d\n", *a);
// keep it clean :
free(a);
return 0;
}
or pass a's address
int f1(int ** b) {
*b = malloc(sizeof(int));
**b = 5;
}
int main() {
int * a;
f1(&a);
printf("%d\n", *a);
// keep it clean :
free(a);
return 0;
}
It looks like you're misunderstanding a fundamental part of how C works - namely that it is a 'pass-by-value' language. In order for main() to know about the memory you allocated, you have to get it back out. The following code will do you what you want:
int f1(int **b)
{
*b = malloc(sizeof(int));
**b = 5;
}
int main(int argc, char **argv)
{
int *a;
f1(&a);
printf("%d\n", *a);
return 0;
}
There are a couple differences between this code and yours; first, the signature of f1() has changed, so that it can return the result of the malloc() call in the passed in pointer. Next, the call to f1() has been changed to pass the address of a rather than a itself - important if you want it to be 'filled-in' by f1(), so to speak. Finally, the printf() in main() has been changed to print out the pointed-to value rather than the pointer itself.
The memory itself persists, but it leaks because you're not providing the allocated pointer to the caller. Also, you're printing a when you should be printing *a. Finally, you're not returning an int from f1.
Try:
void f1(int **b) {
*b = malloc(sizeof(int));
**b = 5;
}
int main() {
int *a;
f1(&a);
printf("%d\n", *a);
free(a);
return 0;
}
Lets suppose you assign a value of NULL to a before you call function f1. Now the way f1 is defined it takes its argument(pointer to an int) by value. That is b will be another variable of type int * which will be a copy of a. So b too will have a value of NULL. Now in f1 you change the value by b by assigning it the address of memory allocated dynamically using malloc. Lets say that memory address is 0x123. As a result of this assignment, b has changed its value from NULL to 0x123 but a(in main) continues to hold NULL, because changing b will not change a, as they are two separate variables. As a result of this when you return from function f1 a will remain unchanged.
There are 2 ways to solve this. One you can make the function f1 return the value of the changed b and then assign it back to a in main and two, you can pass the a by address so that any changes made in f1 will affect a in main too.
// f1 now returns the value of b.
int* f1() {
int *b = malloc(sizeof(int));
*b = 5;
return b;
}
int main() {
int *a = NULL;
a = f1(); // assign the return value of f1 to a.
printf("%d\n", *a); // prints 5...not its *a not just a.
return 0;
}
.
// f1 now takes the address of a.
void f1(int **b) {
*b = malloc(sizeof(int)); // you are actually altering a indirectly.
**b = 5;
}
int main() {
int *a = NULL;
f1(&a); // now pass the address of a to f1.
printf("%d\n", *a); // prints 5...not its *a not just a.
return 0;
}
The address int *b is deleted when the function return. To save it, you need to use a pointer of a pointer
int f1(int ** b) {
*b = malloc(sizeof(int));
**b = 5;
}
Your problem is actually not related to malloc, but rather the fact that you're passing the value the pointer currently holds, rather than the address of it. Try the following:
int f1(int ** b) {
*b = malloc(sizeof(int));
**b = 5;
}
int main() {
int * a;
f1(&a);
printf("%d\n", *a);
return 0;
}
By passing the pointer value as you were, there was no way for the value malloc created to be stored into the pointer.
I have the following code:
int takeEven(int *nums, int numelements, int *newlist) {
newlist = malloc(numelements * sizeof *newlist);
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if (!(*nums % 2)) {
*(newlist++) = *nums;
found++;
}
}
newlist -= found;
printf("First number found %d\n", *newlist); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
The output of the above code:
-1
2088999640
2088857728
If I try printing the first element of the newlist pointer before returning the function (printf("First number found %d\n", *newlist);), it works as intended, but why is it that when I try to access the pointer from outside of the function I get those values from seemingly unmalloced addresses?
You are passing the newList pointer by value, so it will not be modified by your function. You should do instead.
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof *newlist);
...
}
...
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
You need to pass in a pointer to pointer, i.e. int **newlist. Specifically, newlist is being passed into your function by value, so the newlist in main and inside your function are two completely different variables.
There is also a bug in your test for even numbers:
#include <stdio.h>
#include <stdlib.h>
int takeEven(int *nums, int numelements, int **newlist) {
int *list = malloc(numelements * sizeof **newlist);
*newlist = list; // this modifies the value of newlist in main
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if ((*nums % 2) == 0) {
*(list++) = *nums;
found++;
}
}
list -= found;
printf("First number found %d\n", *list); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
You can also take a look at this question from the C-FAQ which deals with your problem also:
Q: I have a function which accepts, and is supposed to initialize, a pointer:
void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}
But when I call it like this:
int *ip;
f(ip);
the pointer in the caller remains unchanged.
A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. In the code above, the called function alters only the passed copy of the pointer. To make it work as you expect, one fix is to pass the address of the pointer (the function ends up accepting a pointer-to-a-pointer; in this case, we're essentially simulating pass by reference):
void f(ipp)
int **ipp;
{
static int dummy = 5;
*ipp = &dummy;
}
...
int *ip;
f(&ip);
Another solution is to have the function return the pointer:
int *f()
{
static int dummy = 5;
return &dummy;
}
...
int *ip = f();
See also questions 4.9 and 4.11.
The newlist you have at the end of the function is not the same as you have when calling the function.
You are passing a copy of a pointer, then malloc changes that pointer(internal to the function) to point to allocated memory, but the outside one is still unmodified.
You need to use a pointer to pointer as a parameter so that you can set where the ourtside one points by double indirection.
int use_pointed_memory(char **pointer){
*pointer = malloc();
}
char *myptr;
use_pointed_memory(&myptr);
So effectively you are giving the function the place where you store the address of what you want and asking the function to store there a valid memory pointer.
You're passing a pointer by value here:
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
Which means that a copy of the pointer is made within that function. You then overwrite that copy:
newlist = malloc(numelements * sizeof *newlist);
Since it is but a copy, the caller won't see the result of your assignment. What you seemingly want here is to pass a pointer by reference - for that, you need a pointer to pointer:
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof **newlist); // apply * to newlist
...
}
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
And don't forget to free:
free(evenNums);
In C, everything is passed by value. So you are passing a copy of evenNums to the function. Whatever you modify it inside the function doesn't get reflected outside. You need to int** as the third parameter.