I have following code, and I want to change array passed trough multiple functions like this:
int main(void)
{
int *arr, n;
scanf("%d", &n);
arr = (int*)malloc(n*sizeof(int));
for (i = 0; i < n; i++)
//scanning into array
func1(arr, n);
}
Now I want each loop to change array and then use the changed arr in next loop etc
void func1(int *x, int h)
{
for (int i = 1; i < height; i++)
change(&x, h, i);
}
Here I need to change the original array to be same as gArr or have same values
void change(int **x, int h, int i) {
int *gArr = (int*)malloc(h*sizeof(int));
//doing some operations
//here I want to somehow change the original array to be gArr
//or to have the same values as gArr
*x = gArr;
}
I've tried multiple approaches and I somehow can't get the right result, thanks for help.
Your call graph is:
main(void)
func1(int *x)
change(int **x)
so if you pass a pointer variable from main, through func1 to change and then change the variable (i.e. the memory location pointed to), then you must also pass its address to func1, otherwise main can never observe the change:
main(void)
func1(int **x)
change(int **x)
...and don't forget to free the original array in change.
You need to distinguish between a pointer to an array, and the elements of that array. Let's first go through what you're doing right now:
int main(void)
{
int *arr, n;
scanf("%d", &n);
arr = (int*)malloc(n*sizeof(int));
// ...
func1(arr, n);
}
int *arr declares a pointer to an int in the scope of the function main().
At some pointer later you pass this pointer to the function func1. Now C is a pass by value language, that means that func1 gets the value of arr, and that value is the address of your dynamically allocated array. This allows your to manipulate the elements that arr points to, but not arr itself. So if inside func1 you have:
void func1(int *arr, int n) {
arr = dynamic_pointer_to_another_array();
}
only the arr inside of func1 is gonna change but not the one in main. Now you've partially figured that out, because your change() function takes a pointer to pointer instead, however in func1() you have:
change(&arr, h, i);
You might think the & here is passing the address of arr from main, but it's actually passing the address of arr from func1, because once again C is a pass by value language. Every time you pass a value to a function it gets copied to that function's scope, and any operations on the value won't be reflected in the caller.
The simple solution to this is to change func1 to take a int **arr instead of int *arr, that way you can do:
change(arr, h, 1);
and inside change you can then do:
*arr = new_array();
This would work because then you're passing the address of the pointer instead of the pointer itself, and through the address of the pointer you can change what the pointer points to.
Important Note
Your code has another huge problem. You're dynamically allocating an array and then trying to reassign the pointer to that array to another array. This is gonna certainly cause memory leaks and dangling pointers. Doing
int *arr = malloc(sizeof(int) * N);
arr = new_array();
is guaranteed to cause memory leaks, because you never use free on that pointer to deallocate the memory, and after you reassign it to another array, you lose all references to it. You have a couple of options of how to go about this. If you need to grow the size of arr then you use realloc instead of allocating a new array. That way you'll still have to only free once.
So the problem is your change of altering value inside the address doesn't take affect right, HOW COULD IT BE UPDATED, when you are dealing with a copy of the array you made in the main.
I've seen you have used int** type inside the parameter list of the function change(int**, int, int). And the reason to use this because the change can take effect on the passed array right!
In the same way, You should also use int** inside like this func1(int**) so that operation can reflect on the original one.
I somehow figured it out this way:
void func1(int *x, int h)
{
for (int i = 1; i < height; i++)
change(x, h, i);
}
void change(int *x, int h, int i) {
int *gArr = (int*)malloc(h*sizeof(int));
//doing some operations
memcpy(x, gArr, h*sizeof(int));
free(gArr);
}
memcpy did the job, but I'm not sure if its the right approach.
Related
This variable num remains at 0. I suspect this is because I am passing in a NULL pointer, but I am constrained to the main (and parameters) as is. How do I adjust the content of the helper function to update num correctly?
int main(void) {
int * num_results = NULL;
int num = 4;
set(num_results, num);
printf(ā%d\nā, *num_results);
return 0;
}
void set(int * results,num){
num_results = malloc(sizeof(int));
*num_results = num;
}
I'm going to guess what you really mean with your question and try to give a decent answer.
I guess you want to change num_results to be equal to num by passing it to the function set as a pointer, and I can see a few mistakes you've made:
You probably have this in your full code, but don't forget to #include <stdio.h> to use printf() and to #include <stdlib.h> to use malloc()
Your function set() should be declared before main(), you can do this by declaring a prototype before main() or simply defining the set() function before main().
Now let's go to your solution: you want to pass the num_results as a parameter to a function, allocate some memory and assign the address to num_results and then update the value to the one in num.
When you pass an int * as a parameter, I guess you already know that by passing int you are simply giving a copy of what is inside an int variable. This works the same way with an int *, you are not passing a reference to num_results so that you can update the address of the pointer, you are passing a copy of the current address, NULL, which will not be modified. What could be modified is what is inside of the current address, but the current address is NULL, so not can really be modified.
Since you want to allocate memory and assign its address to num_results, you must pass a pointer to a pointer, so you are passing the address of where your int* variable is being kept and where you can actually change it.
This way, your function should look like void set(int ** results, int num) and you should call it with set(&num_results, num), so you are passing a reference to num_results, where you can change the address it points to, currently NULL and then the address returned by malloc().
You'd also have to change the body of your function, because you're now using an int **, you want to assign the new address to *results, because results == &num_results, and assign num to **results, because *results = num_results.
I hope my explanation is not very confusing and hopefully someone can explain it better with another answer or by editing mine. Final code:
#include <stdio.h>
#include <stdlib.h>
void set(int ** results, int num){
*results = malloc(sizeof(int));
**results = num;
}
int main(void) {
int * num_results = NULL;
int num = 4;
set(&num_results, num);
printf("%d\n", *num_results);
return 0;
}
set(num_results, num);
Here NULL is getting passed to results variable in set(), when you allocate memory to results, NULL is getting replaced by valid memory address, but you need to understand it will be held in results variable only as its a local variable to set()
You should either pass address of num_results to set() so that memory allocated in set() is retained in main(), or just allocate memory to num_results in main function then pass it to set() as done below:
#include <stdio.h>
int main() {
int *num_results = NULL;
int num = 4;
num_results = malloc(sizeof(int));
set(num_results, num);
printf("%d\n", *num_results);
return 0;
}
void set(int *results,int num){
*results = num;
}
Another example would be:
#include <stdio.h>
#include <stdlib.h>
void set(int **r, int num);
int main() {
int *num_results = NULL;
int num = 4;
/*num_results = malloc(sizeof(int));*/
set(&num_results, num);
printf("%d\n", *num_results);
return 0;
}
void set(int **results,int num){
*results = malloc(sizeof(int));
*(*results) = num;
}
How do I adjust the content of the helper function to update num correctly?
That seems the wrong question, as your set() function seems intended to copy the value of num elsewhere, not to update num itself.
One of your problems is where to copy it. Presently, you allocate some memory for that dynamically, and copy it there. That's fine as far as it goes, but the pointer to the allocated memory is not conveyed back to the caller. This is because all C functions pass arguments by value, and in particular, your main() passes the first argument of set() by value (a value of type int *). Modifying the function's copy does not affect its caller's copy -- that's what pass-by-value is all about.
You may be overlooking a simple fact: dynamic allocation is not the only way to obtain a valid pointer value, nor even the the most important or common. When you see a pointer, you should not automatically go looking for malloc(). You can very easily get a pointer from an array, but perhaps even more importantly, you can get a pointer value by applying the address-of operator (&).
For your set() function to do work that its caller can see without resorting to global variables or changing its signature, the caller must pass as the first parameter a valid pointer to an object that the caller can access, such as one of its own local variables. The pointer is passed by value so the function gets a copy, but it's a copy: it points to the same object that the caller's pointer did. The set() function can therefore modify the pointed-to object via its copy of the pointer to it.
So suppose your main() declared its own local variable result, an int. What do you suppose it could do with &result?
In your helper function you should refer to the first parameter name results instead of num_results. Your helper function should be like:
void set(int * results, int num){
results = malloc(sizeof(int));
*results = num;
}
Your code won't compile. Compiler error messages will tell you how to fix them. Here is a fixed one.
#include<stdlib.h>
#include<stdio.h>
int * num_results = NULL;
void set(int * results, int num){
num_results = malloc(sizeof(int));
*num_results = num;
}
int main(void) {
int num = 4;
set(num_results, num);
printf("%d\n", *num_results);
return 0;
}
For the sake of learning it, you can look at the compilation error messages here and try to fix it by yourself:https://segfault.stensal.com/a/XWfv8rxCJHVtAuRQ
Disclaimer: I built stensal.io as a tool to catch memory issues.
I have been learning arrays, but theres one thing that I cant figure out.
I borrowed two books for C and looked online, but found no solution.
My function timesTen multiplies every array elemenet that I have by 10,
then returns pointer of that array back function main()
How can I copy array a[2] directly in array x[2]?
I would usually use for loop, but I cant, because arguments are in two different functions.
Solution has probably got something to do with pointers, so feel free to post sollution here, but is there any way around them aswell?
Heres the source code:
#include <stdio.h>
int timesTen(int a[])
{
int i;
for (i=0;i<2;i++)
{
printf("%d\t", a[i]);
a[i]*=10;
printf("%d\n", a[i]);
}
return a;
}
int main()
{
int i;
int x[2];
int a[2]={10,50};
// i know here's an error, but how do I fix it? I cant put x[0]=timesTen(a[0])
x[2] = timesTen(a);
//also what if there is array a[10], and I want to copy it in x[5]
for (i=0;i<2;i++)
printf("%d\n", x[i]);
return 0;
}
Thanks!
What you need to understand is the distinction between arrays and pointers. When you declare your two arrays in main(), you allocate two times memory for two integers. That's fine. But in C, you simply cannot pass arrays around (as in: implicitly allocate a new slap of memory and copy the data of the source array into this memory region). Instead, any array identifier will decay to a pointer to the first element of the array in almost all situation. So when you write
int x[2];
int a[2]={10,50};
timesTen(a);
this code is precisely equivalent to
int x[2];
int a[2]={10,50};
timesTen(&a[0]);
So, why does that not clash with your declaration of timesTen()? Because array parameters in function declarations decay right there, on the spot, into a pointer! So, your function declaration is precisely equivalent to this one:
int timesTen(int* a) {
This is one of the least understood features of the C language, and admittedly, it is hard to wrap your brain around this, but once you understand what pointer decay means, you will be much more at ease using pointers and arrays.
So, back to your question. Since you passed only a pointer to your array to timesTen(), and since you modify this array, the changes are directly visible in main(). There are two ways to achieve the behavior you want:
You can change the definition of timesTen() to copy the data into a destination array:
void timesTen(int size, int* source, int* dest) {
for(int i = 0; i < size; i++) dest[i] = 10*source[i];
}
int main() {
int x[2];
int a[2]={10,50};
timesTen(2, a, x); //pointer decay!
//x now contains {100, 500}
}
You can copy the data into the destination array before calling your function to modify the destination array:
void timesTen(int size, int* data) {
for(int i = 0; i < size; i++) data[i] = 10*data[i];
}
int main() {
int x[2];
int a[2]={10,50};
memcpy(x, a, sizeof(a)); //the sizeof operator is one of only two places where no pointer decay happens!
timesTen(2, x); //pointer decay!
//x now contains {100, 500}
}
In the function timesTen, since a is an array, each modification made to it in the function is also done to the parameter you passed (call by address not by value). Therefore you don't need to returns anything.
void timesTen(int a[])
{
int i;
for (i=0;i<2;i++) a[i]*=10;
}
And you just call it by:
timesTen(a);
You probably want something like this:
timesTen(a);
memmove(x, a, 2 * sizeof(x[0]));
instead of
x[2] = timesTen(a);
Note that your function does not need to return anything, because it is modifying the array on its original place. In C if you have an array parameter, it means that only a pointer is passed, not the whole array.
in main function:
int *p;
int i;
p = timesTen(a);
for ( i = 0; i < 2; i++ )
{
printf( "%d\n",*(p + i)); // here you can print the values returned from your function
}
Through pointers you could have eaisly managed it
main ()
{
int a[ 2 ];
int *ptr = timesTen(a);
for ( int i=0; i<2 ; i++)
{
printf("%d",ptr[i]);
}
And as far as
x[2] = timesTen(a);
Is concerned note that x[2] will give "value at 2nd adress from adrees of base that is x"
And it is not a variable but it is a value and you cant assign to a value.
Technically x[2] is not a lvalue.
I have been using java for long time but for some reason I need to use C (ANSI C not C++) to write a simple code. I need to pass the pointer from outside to a function, allocate some memory to the pointer and assign some values also before the function return. I have my code like
#include <stdio.h>
#include <stdlib.h>
void test(int *a)
{
int n=3;
// I have to call another function t determine the size of the array
n = estimatesize(); // n >=3
// I tried fix size n=10 also
a = (int*)malloc(n*sizeof(int));
a[0] = 1;
a[1] = 2;
a[2] = 3;
}
void main(void)
{
int *s=NULL;
test(s);
printf("%d %d %d", s[0], s[1], s[2]);
}
I don't know why the code crashes. I thought at the beginning it is estimatesize() return wrong number but even I fix n to 10, the error still there. So I cannot pass a pointer to a function for memory allocation? If so, how can I dynamically create memory inside a function and pass it out? I know it may be a safe problem in this way but I just want to know if it is possible and how to do that. Thanks.
There are two solutions to this: Either return the pointer from the function, or pass the argument by reference.
For the first one, you simply don't take any arguments, instead you return the pointer:
int *test(void)
{
int *a = malloc(...);
...
return a;
}
int main(void)
{
int *s = test();
...
}
For the second one, you need to pass the address of the pointer, in other words a pointer to the pointer, using the address-of operator &:
void test(int **a)
{
*a = malloc(sizeof(int) * 3);
for (int i = 0; i < 3; ++i)
(*a)[i] = i;
}
int main(void)
{
int *s;
test(&s);
...
}
The reason it doesn't work now, is because the pointer (s in main) is passed by copying it. So the function test have a local copy, whose scope is only in the test function. Any changes to a in the test function will be lost once the function returns. And as s is copied for the argument, that means that s in main never actually changes value, it's still NULL after the function call.
Can I do this in C:
void myFunc(int *vp) {
// do some stuff with vp
}
int main() {
int v[5] = {1,2,3,4,5};
myFunc(v);
return 0;
}
I mean, what would be the correct? myFunc(&v); ?
Thanks!!
Arrays decay to pointers when you pass them as arguments. However, array decay is not the same as taking the address of an array.
"Decay" is how some types are transformed when passed as function arguments. Even though v's type is int [5], it becomes int* when you pass it to a function. This is a behavior a lot of people don't like, but there's nothing to do about it.
Note that, on the other hand, the type of &v is int (*)[5], that is, a pointer to an array of 5 integers. This type doesn't decay, that is, it doesn't transform automatically into another type if you pass it as a function parameter (and that's also why it wouldn't work if you used it in your example, since you need a pointer to integers, not a pointer to an array of integers).
The "correct" thing to do (assuming decay is OK) is to do myFunc(v), just as you're doing in your snippet. Keep in mind that you lose array bounds information when you do it.
Yes ... Your code is correct.
Here v==&v[0] array name is equal to address of first element of array
myFunc(v);
passing array name as argument that means you are passing address of first element in array.
void myFunc(int *vp)
Here you are using pointer. which store the address of first element of array which is passed so you can access the block which is covered with the array.by incrementing the pointer location.
And
myFunc(&v);
&v==&&v[0];
&v is address of address of array first element.
Now
void myFunc(int *vp)
Here You got address of address of array first element, This is not pointing to array. Instead pointing some memory location.Now You can't access the array by incrementing the pointer.
Your code is correct It will work....
But you should take extra care to check the boundary condition.
Please look through the code.
void myFunc(int *vp) {
vp[5] = 30;
}
int main() {
int v[5] = {1,2,3,4,5};
int a = 10;
printf("Value of a before fun call %d\n", a);
myFunc(v);
printf("Value of a before fun call %d\n", a);
return 0;
}
similarly
void myFunc(int *vp) {
vp[5] = 30;
myFunc2(vp);
}
void myFunc2(int *vp) {
vp[6] = 30;
}
int main() {
int v[5] = {1,2,3,4,5};
int a = 10;
printf("Value of a before fun call %d\n", a);
myFunc(v);
printf("Value of a before fun call %d\n", a);
return 0;
}
This will result in segmentation fault due to stack curruption. Since local variables are in stack.
" Double pointers are also sometimes employed to pass pointers to functions by reference "
can somebody can explain me the above statement, what exactly does point to function by reference means ?
I believe this example makes it clearer :
//Double pointer is taken as argument
void allocate(int** p, int n)
{
//Change the value of *p, this modification is available outside the function
*p = (int*)malloc(sizeof(int) * n);
}
int main()
{
int* p = NULL;
//Pass the address of the pointer
allocate(&p,1);
//The pointer has been modified to point to proper memory location
//Hence this statement will work
*p=10;
//Free the memory allocated
free(p);
return 0;
}
It means that you have a function that takes a pointer pointer (type int ** for example). This allows you to modify the pointer (what data it is pointing to) much in the way passing a pointer by reference would allow.
void change (int *p) {*p = 7;}
void Really_Change (int **pp) {*pp = null;}
int p = 1;
int *pp = &p;
// now, pp is pointing to p. Let's say it has address 0x10;
// this makes a copy of the address of p. The value of &p is still 0x10 (points to p).
// but, it uses that address to change p to 7.
change(&p);
printf("%d\n", p); // prints 7;
// this call gets the address of pp. It can change pp's value
// much like p was changed above.
Really_Change(&pp);
// pp has been set to null, much like p was set to 7.
printf("%d\n", *pp); // error dereference null. Ka-BOOM!!!
So, in the same way that you can pass a pointer to an int and change the value, you can pass a pointer to a pointer and change its value (which changes what it points to.)
I'll try to explain with both code and plain english :). The explanation may get long, but it will be worth the while.
Suppose we have a program, running its main() function, and we make a call to another function that takes an int parameter.
Conceptually, When you pass a variable as a parameter to a function, you can do so in (roughly speaking) two ways: by value, or by reference.
"By value" means giving the function a copy of your variable. The function will receive its "content" (value), but it won't be able to change the actual variable outside its own body of code, because it was only given a copy.
"By reference", on the other hand, means giving the function the actual memory address of our variable. Using that, the function can find out the variable's value, but it can also go to that specified address and modify the variable's content.
In our C program, "by value" means passing a copy of the int (just taking int as argument), and "by reference" means passing a pointer to it.
Let's see a small code example:
void foo(int n) {
n = 10;
printf("%d\n", n);
}
int main() {
int n = 5;
foo(n);
printf("%d\n", n);
return 0;
}
What will the output of this program be? 10 10? Nope. 10 5! Because we passed a copy of the int, by value and not by reference, foo() only modified the number stored in its copy, unable to reach main()'s copy.
Now, if we do it this way:
void foo(int* n) {
*n = 10;
printf("%d\n", *n);
}
int main() {
int n = 5;
foo(&n);
printf("%d\n", n);
return 0;
}
This time we gave foo() our integer by reference: it's actual memory address. foo() has full power to modify it by accessing it's position in memory, foo() and main() are working with the same copy, and so the output will be 10 10.
As you see, a pointer is a referece,... but also a numerical position in memory. It's similar to an int, only the number contained inside is interpreted differently. Think of it this way: when we pass our int by reference, we're passing an int pointer by value!. So the same by value/by reference logic can be applied to pointers, even though they already are references.
If our actual variable was not an int, but an int reference (pointer), and we wanted main() and foo() to share the same copy of that reference so that foo() can modifiy it, what would we do? Why of course, we'd need a reference to our reference! A pointer to a pointer. That is:
int n; /* integer */
int* n; /* integer reference(pointer). Stores an int's position in memory */
int** n; /* reference to integer reference, or double pointer.
Stores int*'s memory address so we can pass int*s by reference. */
I hope this was useful.