I'm having trouble passing an integer array as a reference, and then modifying the original array.
#include <stdio.h>
// sets the 2 element of i to 5
void setToFive(int *i[10]){
*i[2] = 5;
printf("hello\n");
}
int main(){
int i[10];
setToFive(&i);
// confirm i[2] == 5
printf("%d\n", i[2]);
}
Compiler complains about invalid type
[vinessa#komputilo ch1]$ gcc test.c
test.c: In function ‘setToFive’:
test.c:5:5: error: invalid type argument of unary ‘*’ (have ‘int’)
5 | *i[2] = 5;
| ^~~~~
test.c: In function ‘main’:
test.c:11:15: warning: passing argument 1 of ‘setToFive’ from incompatible pointer type [-Wincompatible-pointer-types]
11 | setToFive(&i);
| ^~
| |
| int (*)[10]
test.c:4:21: note: expected ‘int *’ but argument is of type ‘int (*)[10]’
4 | void setToFive(int *i){
| ~~~~~^
segmentation fault
[vinessa#komputilo ch1]$ ./a.out
Segmentation fault (core dumped)
Have been banging head at problem for hours, please help.
Here you are
#include <stdio.h>
// sets the 2 element of i to 5
void setToFive(int *i){
i[2] = 5;
printf("hello\n");
}
int main(){
int i[10];
setToFive(i);
printf("%d\n", i[2]);
}
If you want to change elements of an array then just pass it by value. In this case the array designator is implicitly converted to pointer to its first element. Using the pointer and the pointer arithmetic you can change any element of the array.
In fact in this case you are passing elements of the array by reference indirectly through a pointer to them.
Pay attention to that these function declarations
void setToFive(int i[100]);
void setToFive(int i[10]);
void setToFive(int i[1]);
void setToFive(int i[]);
are equivalent and declare the same one function declaration of which the compiler adjusts to the following declaration
void setToFive(int *i);
That is as a result the function deals with a pointer.
As for the expression used as an argument in this function call
setToFive(&i);
then it has the type int ( * )[10] because the pointed array is declared like
int i[10];
It is not the same as the type of the parameter int *i[10] that as I already wrote is adjusted by the compiler to the type int **.
You are passing an array of pointers to integers, not an array of integers. You can just remove the various * declarations and operators, and just pass a simple array as the argument (the array argument will decay to a pointer):
#include <stdio.h>
// sets the 2 element of i to 5
void setToFive(int i[10])
{
i[2] = 5;
printf("hello\n");
}
int main()
{
int i[10];
setToFive(i);
// confirm i[2] == 5
printf("%d\n", i[2]);
return 0;
}
Related
The answer should be 1 and 1. But why the result is 1 and 2. Arr is not a global variable.
#include <stdio.h>
void add (int arr[1])
{
arr[0] = arr[0]+1;
}
int main() {
int arr[1]={1};
printf("%d\n",arr[0]);
add(arr);
printf("%d", arr[0]);
return 0;
}
The answer should be 1 and 1
No, it should be 1 and 2.
void add (int arr[1]) creates a local parameter variable named arr, to which you pass the variable also named arr in the caller.
There are two rules in C informally called "array decay", which means that whenever an array is used in an expression or function parameter declaration, it gets adjusted implicitly by the compiler into a pointer to the first element of the array.
So add(arr); is 100% equivalent to add(&arr[0]);.
And the function defintion void add (int arr[1]) is equivalent to void add (int* arr). This always happens, you can't pass arrays by value in C even though void add (int arr[1]) looks like it does that.
For this reason, the arr in your function points at the arr in the caller. And when you update the contents pointed at, you update the contents of the variable in main.
When an array is declared as a function argument, it becomes a pointer. That's just the way it is. Here is a snippet with corresponding errors ans warnings that proves it:
$ cat main.c
void foo(int arg[10]) {
int arr[10];
float *x;
arg = x;
arr = x;
}
$ gcc -c main.c
main.c: In function ‘foo’:
main.c:5:9: warning: assignment to ‘int *’ from incompatible pointer type ‘float *’ [-Wincompatible-pointer-types]
5 | arg = x;
| ^
main.c:6:9: error: assignment to expression with array type
6 | arr = x;
| ^
So in this case, arr is an array, but arg is not. This means that your add function is equivalent to this:
void add (int *arr)
{
arr[0] = arr[0]+1;
}
And when you pass an array to a function, it will automatically decay to a pointer. So the output 1 and 2 is the expected output.
I did a function f which takes as input a (void*), convert it to a (int*) and print the value.
#include <stdlib.h>
#include <stdio.h>
void f(void* p)
{
int *pi = (int*)p;
printf("%d\n", *pi);
}
int main()
{
int x = 1;
int *px = &x;
void *pv = (void*)px;
f(pv);
return 0;
}
Is it possible to implement a function:
void f2(void** pp);
such that it performs the "same" operations of the function f? My goal is to learn how to convert a (int*) to a (void**) and viceversa.
EDIT: error and warning of #tadman code (I did a mistake)
fvv.c: In function ‘f2’:
fvv.c:10:12: warning: initialization of ‘int *’ from incompatible pointer type ‘int **’ [-Wincompatible-pointer-types]
10 | int *pi = (int**)p;
| ^
fvv.c:12:17: error: invalid type argument of unary ‘*’ (have ‘int’)
12 | printf("%d\n", **pi);
|
EDIT2
fvv.c: In function ‘main’:
fvv.c:19:5: warning: passing argument 1 of ‘f2’ from incompatible pointer type [-Wincompatible-pointer-types]
19 | f2(&px);
| ^~~
| |
| int **
fvv.c:7:16: note: expected ‘void **’ but argument is of type ‘int **’
7 | void f2(void** p)
You can take any level of indirection you want, up to the blatantly, utterly absurd (void*******), but I'm not sure why this would be useful:
void f2(void** p)
{
// Note you must maintain the same level of indirection
int **pi = (int**)p;
// Since this is a ** pointer, it requires ** to fully de-reference
printf("%d\n", **pi);
}
To call this you need a pointer to a pointer:
int x = 1;
int *px = &x;
f2((void**) &px);
In C terms a pointer to a pointer is often interpreted to mean one of the two following things:
A two dimensional array
A mutable pointer argument
Neither of those apply here.
That being said, in C there's not a lot of rules as to what you can and can't convert. If you want to do it, C isn't going to get in your way, even if the resulting code makes no sense or will crash immediately when executed.
You can convert int* to void** and back again, C won't care, but you should have a really good reason for doing such a thing. Normally arbitrary pointers are almost always specified as void*, and as this can be recast into whatever you want, it's sufficient.
For example, you can specify void* as an argument when that pointer is actually int**, something you'll see quite often, as in thread_create taking a void* arg argument. That's not limited to mere pointers, you can cast to your heart's content.
I was doing this exercise and I had to write a program that takes in a list of numbers and swaps pairs of numbers so they're in order:
void swapPairs(int* a[], int length)
{
int i=0;
int temp;
while(i<(length-1))
{
if(a[i]>a[i+1])
{
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
}
i++;
}
}
int main()
{
int array[]={2,1,3,1};
swapPairs(array, 4);
return 0;
}
I keep getting these errors:
In function ‘swapPairs’:
warning: assignment makes integer from pointer without a cast
temp=a[i];
^
warning: assignment makes pointer from integer without a cast
a[i+1]=temp;
In function ‘main’: warning: passing argument 1 of ‘swapPairs’ from incompatible pointer type
swapPairs(array, 4);
^
note: expected ‘int **’ but argument is of type ‘int *’
void swapPairs(int* a[], int length)
^
When I tried it with just an array instead of a pointer, it worked perfectly fine. Can someone please explain what is wrong with this and how to fix it?
Thanks in advance.
Your declaration of swapPairs is wrong - it shouldn't accept an array of int * (int pointers) - it should accept and an array of ints:
void swapPairs(int a[], int length)
The type of 'temp' is int. The type of 'a[i]' is *int (pointer to an int).
You are assigning the value of a pointer rather than the value of an integer because you are failing to dereference the pointer.
The while loop should read:
while(i<(length-1))
{
if(*(a[i])>*(a[i+1]))
{
temp=*(a[i]);
*(a[i])=*(a[i+1]);
*(a[i+1])=temp;
}
i++;
}
I'm new in programming and learning pointers in array in C. Have a look at the below programmes.
1st program
#include<stdio.h>
int fun();
int main()
{
int num[3][3]={21,325,524,52,0,6514,61,33,85};
fun(num);
printf("%d",*(*(num+1)+1));
*(*(num+1)+1)=0;
printf("%d",*(*(num+1)+1));
return 0;
}
int fun(int **p)
{
*(*(p+1)+1)=2135;
return 0;
}
2nd program
#include<stdio.h>
int fun();
int main()
{
int num[3][3]={21,325,524,52,0,6514,61,33,85};
fun(num);
printf("%d",*(*(num+1)+1));
*(*(num+1)+1)=0;
printf("%d",*(*(num+1)+1));
return 0;
}
int fun(int *p)
{
*((p+1)+1)=2135;
return 0;
}
3rd program
#include<stdio.h>
int fun();
int main()
{
int num[3][3]={21,325,524,52,0,6514,61,33,85};
fun(num);
printf("%d",*(*(num+1)+1));
*(*(num+1)+1)=0;
printf("%d",*(*(num+1)+1));
return 0;
}
int fun(int (*p)[3])
{
*(*(p+1)+1)=2135;
return 0;
}
In the first program **p is used in the fun() function which I think it should be correct and in that function I've written *(*(p+1)+1) to change the first element of first array. But on compiling this program it's showing error: invalid type argument of unary '*' (have 'int'). As far as I know num is a pointer to array and it is holding the address of num[1] which is again holding the address of num[1][0].
On compiling the second program compiler is showing no error. And *((p+1)+1)=0 is changing the value of 2nd element of first array. Why it is changing the value of 2nd element of zeroth array not the value of first element of first array? and How? It should be *(*(p+1)+1)=0.
In the third program the compler is showing no error and it is showing the correct result. How?. What does *(p)[3] mean?
I had searched about this but couldn't found the satisfactory result.
All of your programs are ill-formed. Your compiler must produce warning or error messages, and the output of any executable produced is meaningless.
They are ill-formed because int[3][3] is not compatible with int **, nor with int *, nor with int *[3].
To pass int[3][3] to a function, the function must accept int (*)[3] and nothing else (well, except for void *).
This is because arrays can be converted to a pointer to the first element of the array. (In C syntax, num can be used to mean &num[0]).
In C, there are only truly one-dimensional arrays; an array of type int[3][3] is considered to be an array of 3 elements, each of which is an array of 3 ints.
So a pointer to the first element of num is a pointer to an array of 3 ints, which is written as int (*p)[3]. You could write:
int (*p)[3] = &num[0];
or the shorthand for the same thing:
int (*p)[3] = num;
NB. You continually write *(*(num+1)+1)) which is difficult to read. Instead of this, num[1][1] seems much clearer.
In C, x[y] is always exactly equivalent to *(x+y).
I think you are asking: What's the difference between
int fun(int *p)
and
int fun(int (*p)[3])
The first one expects a pointer to an int. The second one expects a pointer to an array of 3 ints.
You are able to call to both these functions using num since you declared the function as
int fun();
If you declare the functions like they are defined, you will get compiler error/warning for the first version.
Here's an updated version of your code and the resulting compiler warning, using gcc and compiler flag -Wall.
#include <stdio.h>
int fun(int *p);
int main()
{
int num[3][3]={21,325,524,52,0,6514,61,33,85};
fun(num);
return 0;
}
int fun(int *p)
{
*(p+0)=2135;
return 0;
}
test.c: In function ‘main’:
test.c:7:4: warning: missing braces around initializer [-Wmissing-braces]
test.c:7:4: warning: (near initialization for ‘num[0]’) [-Wmissing-braces]
test.c:8:4: warning: passing argument 1 of ‘fun’ from incompatible pointer type [enabled by default]
test.c:3:5: note: expected ‘int *’ but argument is of type ‘int (*)[3]’
Why the following code is giving segmentation fault error
#include<stdio.h>
int main()
{
int i;
int a[2][2]={1,2,3,4};
int **c;
c=a;
for(i=0;i<4;i++)
printf("%d",*(*(c)+i));
}
This assignment:
c=a;
Should give you a warning. a decays into a pointer to its first element, which has type int (*)[2]. Assigning that type to a variable of type int ** requires an explicit cast.
Redeclaring c should fix your problem:
int (*c)[2];
Example warning from clang:
example.c:8:6: warning: incompatible pointer types assigning to 'int **' from
'int [2][2]' [-Wincompatible-pointer-types]
c=a;
^~
1 warning generated.
Read the comments of the following code:
#include<stdio.h>
int main()
{
int i;
int a[2][2]={{1,2},{3,4}}; // Put each dimension in its braces
/*int a[2][2]={1,2,3,4};
This declaration of array make the following:
a1[ONE] a2[TWO] THREE FOUR
a3[Unknown value] a4[Unknown value]
i.e. the numbers 3 and 4 are being written beyond of the array...
*/
int *c1;
int **c2; // `int **` is a pointer to a pointer, so you have to
c1=&a[0][0]; // declare a pointer `c1` and then assign to it `c2`.
c2=&c1; // AND use `&` to assing to pointer the address of
// variable, not its value.
for(i=0;i<4;i++)
printf("%d",*(*(c2)+i)); // here is `double dereference` so here must be `c2`
// (ptr-to-ptr-to-int) but not c1 (ptr-to-int).
return 0; // AND make the `main()` to return an `int` or
// make the returning type `void`: `void main(){}`
// to make the `main()` function to return nothing.
}
This is a problem in the definition of c. int **c; Suggests that this is a pointer to a pointer, but the definition of a is of type int *[2]. Changing the definition of c to int (*c)[2] should do the trick.