statically allocated array as function argument in C - c

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.

Related

Change array inside multiple functions via pointers

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.

When using a multi-dimensional array, What is the difference between using the pointer to that array and using actual array name as pointer

I have this code, Which uses function to which a pointer to an array is passed
#include<stdio.h>
void func(int ptr[][3])
{
printf("%d %d",*ptr,*ptr+1);
}
void main()
{
int arr[2][3]={{1,2,3},{4,5,6}};
int (*ptr)[3]=arr;
func(ptr);
}
Now, If I pass the actual array name to the function as
#include<stdio.h>
void func(int ptr[][3])
{
printf("%d %d",*ptr,*ptr+1);
}
void main()
{
int arr[2][3]={{1,2,3},{4,5,6}};
int (*ptr)[3]=arr;
func(arr);
}
Both of the above code executes and prints the same address. But what is the point of having a pointer if array name of multi-dimensional array does the same job.
Or is there any difference between them?
This:
printf("%d %d",*ptr,*ptr+1);
...isn't doing what I'd guess you intend it to. In particular, the precedence means that *ptr+1 means the same as (*ptr)+1, whereas I'd guess what you really wanted was:
*(ptr + 1)
To get an idea of the real difference between the two, it might make more sense to not dereference the pointers at all, and just print out the addresses:
void func1(int *a) {
printf("%p %p\n", (void *)a, (void *)(a+1));
}
void func2(int ptr[][3]) {
printf("%p %p\n", (void *)ptr, (void *)(ptr+1));
}
int main() {
int x[] = {1, 2, 3};
printf("sizeof int == %d\n\n", (int)sizeof(int));
func1(x);
func2(&x);
}
Now let's look at the result:
sizeof int == 4
0x7ffe3f67ba20 0x7ffe3f67ba24
0x7ffe3f67ba20 0x7ffe3f67ba2c
The first shows addresses ending in f00 and f04. As shown, sizeof(int) == 4, so we're seeing pretty much what we expect--adding 1 to an int * yields a pointer to the next int, so the address is increased by 4.
In the second case, the addresses end with a20 and a2c, so we're seeing a difference of c (12 decimal). In this case, it's not a pointer to an int--it's a pointer to an array of three ints. So, when we add one, the address changes by the size of an array of three ints of 4 bytes apiece (i.e., 3x4 = 12).
But what is the point of having a pointer if array name of multi-dimensional array does the same job.
The point is that an array is something completely different than a pointer and of course, you could have a pointer without an array.
The array holds many objects of the same type in a contiguous memory region. So pointer vs array makes a (huge) difference for the declaration.
Taking a pointer of an array just to pass it along is not necessary because that happens automatically in C. It doesn't hurt either.

how to declare a function to accept a pointer to an array of ints

Sorry if this seems like a freshman CS question but I'm trying to pickup some objective c and reviewing pointers and I'm trying to pass a pointer to an array of ints (see all caps comment for problem - caveat I could be REALLY confused about how all this works; I promise I knew it once).
I have:
int (*d)[]; //a pointer to an array of ints.
int e[3]={12,45,789};
d=&e; // works
a=g(d);
NSLog(#"here is %i", a);
...
// THIS PART IS THE PROBLEM
// trying to declare for passing a pointer array of ints
int g(int []); // no
int g(int *[]); // no
int g(int (*)[]); // no
int g(myArray){ // ERROR conflicting types for g
return 2313459;
}
How would I declare this function to accept a pointer to an array of ints (or is there something else I want to be doing)?
thx
You may pass an array either via a pointer to the array or via a pointer to the first element. Samples are:
#include <stdio.h>
int g(int (*A)[]) // A is a pointer to an array.
{
return (*A)[1];
}
int h(int A[]) // A is a pointer to the first element.
{
return A[1];
}
int main(void)
{
int (*d)[];
int e[3] = { 12, 45, 789 };
d = &e;
printf("%d\n", g(d)); // Pass a pointer to the array.
printf("%d\n", g(&e)); // Pass a pointer to the array.
printf("%d\n", h(*d)); // Pass a pointer to first element.
printf("%d\n", h(e)); // Pass a pointer to first element.
return 0;
}

passing pointer as size of an array in C

I want to pass a pointer as a size element of an array
example:
void hello(int array1[how can i refer pointer "ptr" here][2])
{
// i want to access the array used in the main() here
printf("hi");
}
int main()
{
int c=5;
int *ptr=&c;
a[*ptr][2];
a[0][1]=0;
a[0][2]=4;
}
I apologize for not being clear with my question here , i want to access the array used in the main() function in my hello() function.
You will have to use the value pointed to by the pointer:
a[*ptr][2];
ptr is the address pointed to by the pointer not the value stored there. You use the dereference operator * to get the value.
Of course, ptr is not of type int, it's of type int * (integer pointer). An array subscript must be of type int.
Maybe what you want is a[*ptr][2].
You need to deference the pointer by using *ptr so
int c = 5;
int *ptr = &c;
a[*ptr][2];
otherwise you are not using the value of ptr you are using its address in memory which returns an error.
Use the dereference operator *:
a[*ptr][2];
The expression *ptr tells the compiler to use the value pointed to by ptr.
As for your updated question, that's not possible. But it's not needed either, as it's passed as a pointer anyway.
When declaring a function, this:
void foo(int a[5][5])
is the same as this:
void foo(int a[][2])
And also the same as this:
void foo(int (*a)[2])
It has pretty much been answered already, you can't call an adress in the array a[0x3950f2][2]
Always use the pointer* to get the position in the array a[*ptr][2] to get the expected value - in this case: a[*ptr][2] == a[5][2]. You may read this.
Edit to your updated question: You can't to this. You can use the pointer when you call the function or when using the variable in the function.
Your second edit:
void hello(int **array1)
{
// i want to access the array used in the main() here
printf ("hi");
a[0][0] = 24;
}
int main()
{
int c = 5;
int *ptr = &c;
int **a;
a[*ptr][2];
a[0][1] = 0;
a[0][2] = 4;
hello (a);
return 0;
}

I'm trying to make 2d array, pass it to function and then update the modified array in main

The compiler shows:
Warning: passing argument 1 of 'fun' from incompatible
pointer type; note: expected 'int ()[5]' but argument
is of type 'int (*)[5][5]'
Code:
#include<stdio.h>
void fun(int * b[][5])
{
int x=11,y=90;
printf("here");
*b[1][3] = x;
*b[3][1] = y;
*b[2][2] = x + ++y;
}
int main()
{
int a[5][5];
a[1][3] = 12;
a[3][1] = 145;
fun(&a);
printf("%d %d %d",a[1][3],a[3][1],a[2][2]);
}
You do not need the asterisk in your function parameters, and you don't need to dereference the array b in your function. Arrays are passed by reference (so get rid of the ampersand in foo(&a) as well), because C treats them as pointers to the first element in the sequence.
Multidimensional arrays are treated as arrays of pointers to the start of smaller sub-arrays, i.e. arrays-of-arrays. Same explanation as above applies.
Your code should look like this in the end:
void fun(int b[][5]) // can also be (int (*b)[5]), i.e. array of 5 pointers
{
int x=11,y=90;
b[1][3] = x;
b[3][1] = y;
b[2][2] = x + ++y;
}
int main()
{ // ...
fun(a);
// ...
}
int a[5][5]; //is an 2d int array
When arrays are passed to a function, what really gets passed is a pointer to the arrays first element.
So calling the fun() function with fun(a) will actually pass the pointer to the a first element, in this case an int array of size 5. The function fun() will receive a pointer to an int array of size 5, that is to say int (*b)[5]. Note that int *b[5] is not the same and is an array of size 5 containing int pointers.
Your fun function can either have:
void fun(int b[][5])
or
void fun(int (*b)[5])
The first way to do it says that the function will receive a 2d array of ints, but since we know that what actually will be sent to the function is a pointer to the first element of the array a, the compiler will quietly compile the function as if the parameter were a pointer, since it's a pointer that it will receive.
The second way to do it explicitly shows what type it will receive, a pointer to an array of size 5.

Resources