How do you pass an array to a function using pointers - arrays

I am trying to print an array through a function by using call by reference but keep getting a warning:
passing argument 1 of 'test' from incompatible pointer type [-Wincompatible-pointer-types]
I tried replacing test(&arr, n); with test(arr, n);, test(*arr, n);, test(&arr[], n);, test(*arr[], n);, test(&arr[], n);
but nothing worked, what am I doing wrong?
#include<stdio.h>
void test(int *a[], int b);
void main()
{
int arr[]={1, 2, 3, 4, 5}, i, n=5;
test(&arr, n);
}
void test(int *d[], int n)
{
int i;
for(i=0; i<n; i++)
{
printf("%d", *d[i]);
}
}

How do you pass an array to a function
Just by using a pointer of the array element type:
void test(int *a, int b);
If you then pass an array to the function:
test(arr);
... the C compiler will pass a pointer to the first element of the array (&(arr[0])) to the function.
Note that you don't use the & in this case.
Inside the function you can use array operations:
void test(int * arr)
{
arr[3] = arr[2];
}
(In your case: printf("%d\n", arr[n]);)
(This is true for any kind of pointer data type with exception of void *. The C compiler assumes that the pointer points to the first element of an array if you use array operations with pointer data types.)
"passing argument 1 of 'test' from incompatible pointer type"
As far as I know, [] in a function argument is not interpreted as array, but as pointer. For this reason, ...
void test(int *a[], int b);
... is interpreted as:
void test(int **a, int b);
... which means that the C compiler expects a pointer to an array of pointers (int *), not to an array of integers (int).

It's much simpler than that. In the example below I'm using size_t to express array size, it's an unsigned integer type specifically meant to be used for that purpose.
#include <stdio.h>
// you can use the size parameter as array parameter size
void test (size_t size, int arr[size]);
int main (void) // correct form of main()
{
int arr[]={1, 2, 3, 4, 5};
test(5, arr);
}
void test (size_t size, int arr[size])
{
for(size_t i=0; i<size; i++) // declare the loop iterator inside the loop
{
printf("%d ", arr[i]);
}
}

Related

Unsized Matrixes in C: how to pass them as an argument to a function, manipulate and return them in my code?

I would like to know how to pass a matrix of variable lines and columns to a function, transform it inside the function and them returning it in C.
Here lies the code I am trying to build to make it happen.
#include <stdio.h>
#include <stdlib.h>
void **f(int **m, int w, int h);
int main()
{
int A[3][3]={{1,2,3},{4,5, 6},{7,8,9}};
int B[3][2]={{1,2},{3, 4}, {5, 6}};
f(A, 3, 3);
f(B, 3, 2);
return 0;
}
void **f(int **m, int w, int h )
{
int i,j;
int n[w][h];
for(i=0;i<w;i++)
{
for(j=0;j<h;j++)
n[i][j] = m[i][j] + 1;
printf("%5d", m[i][j]);
}
return 0;
}
Whose compilation is returning the following errors:
main.c:20:5: warning: passing argument 1 of ‘f’ makes pointer from integer without a cast [->Wint-conversion]
main.c:13:8: note: expected ‘int **’ but argument is of type ‘int’
main.c:21:5: warning: passing argument 1 of ‘f’ makes pointer from integer without a cast [->Wint-conversion]
main.c:13:8: note: expected ‘int **’ but argument is of type ‘int’
Segmentation fault (core dumped)
Though multi-dimensional arrays have long been second-class citizens in C, modern versions give them much better support. If the array sizes are included prior to the actual array in the list of function parameters, they can form dimensions of that array. Note that A and B are now the last parameter to the function f():
void f(int w, int h, int m[w][h]);
int main()
{
int A[3][3]={{1,2,3},{4,5, 6},{7,8,9}};
int B[3][2]={{1,2},{3, 4}, {5, 6}};
f(3, 3, A);
f(3, 2, B);
return 0;
}
void f(int w, int h, int m[w][h])
{
int n[w][h];
int i, j;
for(int i;i<w;i++)
{
for(int j;j<h;j++)
n[i][j] = m[i][j] + 1;
printf("%5d", m[i][j]);
}
}
I don't recall which version of C introduced this, but for sure the int **m parameter is incorrect because m is not a pointer to a pointer (or an array of pointers).
It's also important that this syntax doesn't force arrays to be re-ranked according to the parameters, so if an array is [10][3] when you define it, it ought to be [10][3] when you describe it to a function. This is syntactic sugar for array access only.

Passing array to function by value or reference the same?

I want to know if there is any real difference; I have written code that as it feel it a passing by copy not reference but it acts as reference.
Here is the code:
#include <stdio.h>
#include <conio.h>
using namespace std;
int pause = 0;
void display(int b[5], int size){
for (int i = 0; i < size; i++){
printf("\n%d",b[i]," at:");
printf(" %d", &b[i]);
}
}
void main(){
int num[] = { 2, 4, 6, 8, 10 };
printf("\nIn main function.");
for (int i = 0; i < 5; i++){
printf("\n%d", num[i], " at:");
printf(" %d", &num[i]);
}
display(num,5);
scanf("%d", pause);
}
You cannot pass an array itself to a function at all, nor can you return one. In particular, despite the appearance of its declaration, your function display() does not receive an array as a parameter. It's declaration is 100% equivalent to this one:
void display(int *b, int size);
and this one:
void display(int b[], int size);
Expressions of array type are automatically converted to pointers in almost every context in which they can appear, so this function call:
display(num,5);
is equivalent to
display(&num[0],5);
Nevertheless, there is a potential difference to call out in this area: the expression &num is not equivalent to &num[0]. They refer to the same address, but the two expressions have different types. Passing the former would be the analog of passing the array by reference, but that expression does not have the correct type for the first argument to your display() function. A function that wants to receive &num needs to be declared differently:
void display2(int (*b)[5]);
or
void display3(int n, int (*b)[n]);
The latter requires C99, or C2011 with VLA support (which is required in C99, but optional in C2011).

C - Copying array in other array as output argument

I am trying understand how pointers works in C. I am trying a simple case where an array, and a pointer to array are the arguments of a function which will copy the elements of the first one in the second one.
I have written this code
#include <stdio.h>
#define TAM 32
typedef int TablaArray[32];
void copyArray(TablaArray, TablaArray*, int);
void main(){
int t1[] = {1,2,3,4};
int t2[4];
copyArray(t1, t2,4);
for(int i = 0; i <= 3; i ++){
printf("%d - %d\n", t1[i], t2[i]);
}
}
void copyArray(TablaArray t1, TablaArray *t2, int tam){
for(int i = 0; i<tam-1; i++){
printf("%d\n", t1[i]);
*t2[i] = t1[i];
}
}
I am expecting to get something like this with the printf expression:
1 - 1
2 - 2
3 - 3
4 - 4
But definitely I don't know the way... I have been looking in stackoverflow and because I am sure this trivial question is already answered... but I didn't find it...
You need to make sure you are passing two int pointers pointing to both arrays. In your code only one of the arguments is a pointer. The code below should make it more clear:
#include <stdio.h>
void copyArray(int * arr1, int * arr2, int size);
int main(void)
{
int t1[] = {1,2,3,4};
int t2[4];
copyArray(t1, t2,4);
for(int i = 0; i <= 3; i ++)
{
printf("%d - %d\n", t1[i], t2[i]);
}
return 0;
}
void copyArray(int * arr1, int * arr2, int size)
{
for(int i = 0; i < size; i++)
{
printf("%d\n", arr1[i]);
arr2[i] = arr1[i];
}
return;
}
Edit: in what you have written, a TablaArray * is a pointer to an array of 32 ints, while you need an int *
typedef int TablaArray[32];
is bad practice
The problem is connected with array to pointer decay and then with pointer arithmetics:
Pointer decay means that if you pass an array-object of type int x[32] as argument to a function, then it "decays" to a pointer like int *, which points to the first element of the integer array. So be aware that if you pass an int x[32]-object, it's actually passed by reference (the array is not copied) and you may alter the contents of the array in the function.
Now pointer arithmetics:
Incrementing a pointer (or accessing an array through array subscripting) implicitly does pointer arithmetics, and the number of bytes added to the initial value depends on the type of the object to which the pointer points:
typedef int Array10[10];
Array10 arr = { 1,2,3,4,5,6,7,8,9,0 };
int *x = arr; // arrayOfInts decays to a pointer; x points to the &arr[0]
x++; // in terms of bytes, x is incremented by sizeof(int) bytes
int i = x[3]; // gets the int-value on the address of x + 3*sizeof(int)
Array10 *arr10ptr = arr;
arr10ptr++; // in terms of bytes, x is incremented by sizeof(Array10) bytes, which is 10*sizeof(int)
arr10ptr[3]; // 3*sizeof(Array10), i.e. 3*10*sizeof(int)
Now it should be clear why a function parameter being declared as a pointer to an array of int[32] behaves different from a function parameter being declared as an int[32].
So you could correct your program as follows, now knowing that TablaArray t2 will be a reference to the underlying array anyway:
void copyArray(TablaArray t1, TablaArray t2, int tam){
for(int i = 0; i<tam; i++){
printf("%d\n", t1[i]);
t2[i] = t1[i];
}
}
Hope it helps.
Compile with warnings enabled. If you used gcc -Wall -Werror, you would get the following errors:
luis.c:10:6: error: return type of ‘main’ is not ‘int’ [-Werror=main]
void main(){
^~~~
luis.c: In function ‘main’:
luis.c:15:19: error: passing argument 2 of ‘copyArray’ from incompatible pointer type [-Werror=incompatible-pointer-types]
copyArray(t1, t2,4);
^~
luis.c:8:6: note: expected ‘int (*)[32]’ but argument is of type ‘int *’
void copyArray(TablaArray, TablaArray*, int);
^~~~~~~~~
cc1: all warnings being treated as errors
The first one is simple, it should be int main.
The second one is a bit harder to see exactly because you used a typedef. So your prototype is now
void copyArray(int *, int (*)[32], int);
With the second value being a pointer-to-array that by itself is a construct that is not used often.
Instead, you'd just need two pointers to int here, and the size of an array should perhaps use size_t instead:
void copyArray(int *, int *, size_t);
void copyArray(int *t1, int *t2, size_t n){
for (int i = 0; i < tam; i++) {
t2[i] = t1[i];
}
}
Finally, if you use a C99, C11 compiler, it could be nice to use the variable-length arrays arrays to tell that one of the parameters tell the sizes of the arrays; for that we need to reorder the parameters:
void copyArray(size_t, int[*], int[*]);
void copyArray(size_t n, int t1[n], int t2[n]) {
...
}
void copyArray(TablaArray, TablaArray, int); // prototype
void copyArray(TablaArray t1, TablaArray t2, int tam){
for(int i = 0; i<tam; i++){
printf("%d\n", t1[i]);
t2[i] = t1[i];
}
}
this will help
// much faster
#include <string.h>
void copyArray(TablaArray t1, TablaArray t2, int tam){
memcpy(t2, t1, sizeof(t1[0]) * tam);
}
In Your Copy function you were copying the same value of T1 to T2 on the Address Of T2. you can do it with out pointers but pointers helps you to refer the Address

Passing multidimensional arrays as arguments in functions in C

I am currently doing the fifteen exercise in CS50's Problem set 3. However, I am stuck in figuring out the syntax to pass a multi-dimensional array as an argument to a function. For instance, the following code (which prints out some numbers in an array) compiles and works:
#include <stdio.h>
void func(int array[], int size);
int main()
{
int size = 3;
int array[3] = {1,2,3};
func(array,size);
printf("Done\n");
}
void func(int array[], int size)
{
printf("%i %i %i\n", array[0],array[1], array[2]);
}
But this doesn't:
#include <stdio.h>
void func(int array[][], int size);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(array,size);
printf("Done");
}
void func(int array[][], int size)
{
printf("%i %i %i\n", array[0][0],array[1][1], array[2][2]);
}
This is the error provided by clang:
test.c:3:20: error: array has incomplete element type 'int []'
void func(int array[][], int size);
^
test.c:13:20: error: array has incomplete element type 'int []'
void func(int array[][], int size)
Can anyone explain to me what's wrong with my syntax? I don't quite understand the error messages given to me by clang.
The function func() expects a pointer to int but you are passing a pointer to an array. Hence, the errrors.
It's because an array gets converted into a pointer to its first element when you pass it to a function.
You can change the function prototype and definition to receive a pointer to an array:
void func(int (*array)[3], int size);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(array,size);
printf("Done");
}
void func(int (*array)[3], int size) {
...
}
Note that your array is initialized with size 3x3. So the array size has to 3x3 at least.
C99 allows to you pass dimensions. So you can write it like this too:
void func(int x, int y, int a[x][y]);
int main()
{
int size = 3;
int array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
func(3, 3, array);
printf("Done");
}
void func(int x, int y, int array[x][y])
{
printf("%i %i %i\n", array[0][0],array[1][1], array[2][2]);
}
An array is not a type in C! Internally, it is always handled as a pointer, hence, a pointer to the array is passed as argument and not the array itself.
If you intend to pass arrays as arguments (and not just pointers), you should rethink your design!
If you still need to do this wrap the array into a structure and pass the structure.
struct astruct
{
int size;
int array[3];
};
A declaration like int a[][] isn't sensible, since the compiler must know the size of all dimensions (except of the outermost) to calculate the memory address on access.
I.e. if an array is declared as
int array[][a][b];
The memory address for access to
array[2][1][3];
is calculated by
base_address + (2*a*b + 1*b + 3) * sizeof int
Without knowing a and/or b, this calculation would not be possible.
Simply tell the function to expect a multi-dimensional array:
void func (int array[3][3], int size);
Or if you want the function to be completely flexible:
void func (int x, int y, int array[x][y]);
You need to specify size of array when declaring prototype as well as while defining function . Right now it is of incomplete type .
Try this instead -
void func(int array[][3], int size)

C pass int array pointer as parameter into a function

I want to pass the B int array pointer into func function and be able to change it from there and then view the changes in main function
#include <stdio.h>
int func(int *B[10]){
}
int main(void){
int *B[10];
func(&B);
return 0;
}
the above code gives me some errors:
In function 'main':|
warning: passing argument 1 of 'func' from incompatible pointer type [enabled by default]|
note: expected 'int **' but argument is of type 'int * (*)[10]'|
EDIT:
new code:
#include <stdio.h>
int func(int *B){
*B[0] = 5;
}
int main(void){
int B[10] = {NULL};
printf("b[0] = %d\n\n", B[0]);
func(B);
printf("b[0] = %d\n\n", B[0]);
return 0;
}
now i get these errors:
||In function 'func':|
|4|error: invalid type argument of unary '*' (have 'int')|
||In function 'main':|
|9|warning: initialization makes integer from pointer without a cast [enabled by default]|
|9|warning: (near initialization for 'B[0]') [enabled by default]|
||=== Build finished: 1 errors, 2 warnings ===|
In your new code,
int func(int *B){
*B[0] = 5;
}
B is a pointer to int, thus B[0] is an int, and you can't dereference an int. Just remove the *,
int func(int *B){
B[0] = 5;
}
and it works.
In the initialisation
int B[10] = {NULL};
you are initialising anint with a void* (NULL). Since there is a valid conversion from void* to int, that works, but it is not quite kosher, because the conversion is implementation defined, and usually indicates a mistake by the programmer, hence the compiler warns about it.
int B[10] = {0};
is the proper way to 0-initialise an int[10].
Maybe you were trying to do this?
#include <stdio.h>
int func(int * B){
/* B + OFFSET = 5 () You are pointing to the same region as B[OFFSET] */
*(B + 2) = 5;
}
int main(void) {
int B[10];
func(B);
/* Let's say you edited only 2 and you want to show it. */
printf("b[0] = %d\n\n", B[2]);
return 0;
}
If you actually want to pass an array pointer, it's
#include <stdio.h>
void func(int (*B)[10]){ // ptr to array of 10 ints.
(*B)[0] = 5; // note, *B[0] means *(B[0])
//B[0][0] = 5; // same, but could be misleading here; see below.
}
int main(void){
int B[10] = {0}; // not NULL, which is for pointers.
printf("b[0] = %d\n\n", B[0]);
func(&B); // &B is ptr to arry of 10 ints.
printf("b[0] = %d\n\n", B[0]);
return 0;
}
But as mentioned in other answers, it's not that common to do this. Usually a pointer-to-array is passed only when you want to pass a 2d array, where it suddenly looks a lot clearer, as below. A 2D array is actually passed as a pointer to its first row.
void func( int B[5][10] ) // this func is actually the same as the one above!
{
B[0][0] = 5;
}
int main(void){
int Ar2D[5][10];
func(Ar2D); // same as func( &Ar2D[0] )
}
The parameter of func may be declared as int B[5][10], int B[][10], int (*B)[10], all are equivalent as parameter types.
Addendum: you can return a pointer-to-array from a function, but the syntax to declare the function is very awkward, the [10] part of the type has to go after the parameter list:
int MyArr[5][10];
int MyRow[10];
int (*select_myarr_row( int i ))[10] { // yes, really
return (i>=0 && i<5)? &MyArr[i] : &MyRow;
}
This is usually done as below, to avoid eyestrain:
typedef int (*pa10int)[10];
pa10int select_myarr_row( int i ) {
return (i>=0 && i<5)? &MyArr[i] : &MyRow;
}
In new code assignment should be,
B[0] = 5
In func(B), you are just passing address of the pointer which is pointing to array B. You can do change in func() as B[i] or *(B + i). Where i is the index of the array.
In the first code the declaration says,
int *B[10]
says that B is an array of 10 elements, each element of which is a pointer to a int. That is, B[i] is a int pointer and *B[i] is the integer it points to the first integer of the i-th saved text line.
Make use of *(B) instead of *B[0].
Here, *(B+i) implies B[i] and *(B) implies B[0], that is *(B+0)=*(B)=B[0].
#include <stdio.h>
int func(int *B){
*B = 5;
// if you want to modify ith index element in the array just do *(B+i)=<value>
}
int main(void){
int B[10] = {};
printf("b[0] = %d\n\n", B[0]);
func(B);
printf("b[0] = %d\n\n", B[0]);
return 0;
}
main()
{
int *arr[5];
int i=31, j=5, k=19, l=71, m;
arr[0]=&i;
arr[1]=&j;
arr[2]=&k;
arr[3]=&l;
arr[4]=&m;
for(m=0; m<=4; m++)
{
printf("%d",*(arr[m]));
}
return 0;
}
Using the really excellent example from Greggo, I got this to work as a bubble sort with passing an array as a pointer and doing a simple -1 manipulation.
#include<stdio.h>
void sub_one(int (*arr)[7])
{
int i;
for(i=0;i<7;i++)
{
(*arr)[i] -= 1 ; // subtract 1 from each point
printf("%i\n", (*arr)[i]);
}
}
int main()
{
int a[]= { 180, 185, 190, 175, 200, 180, 181};
int pos, j, i;
int n=7;
int temp;
for (pos =0; pos < 7; pos ++){
printf("\nPosition=%i Value=%i", pos, a[pos]);
}
for(i=1;i<=n-1;i++){
temp=a[i];
j=i-1;
while((temp<a[j])&&(j>=0)) // while selected # less than a[j] and not j isn't 0
{
a[j+1]=a[j]; //moves element forward
j=j-1;
}
a[j+1]=temp; //insert element in proper place
}
printf("\nSorted list is as follows:\n");
for(i=0;i<n;i++)
{
printf("%d\n",a[i]);
}
printf("\nmedian = %d\n", a[3]);
sub_one(&a);
return 0;
}
I need to read up on how to encapsulate pointers because that threw me off.
The argument of func is accepting double-pointer variable.
Hope this helps...
#include <stdio.h>
int func(int **B){
}
int main(void){
int *B[10];
func(B);
return 0;
}
In the function declaration you have to type as
VOID FUN(INT *a[]);
/*HERE YOU CAN TAKE ANY FUNCTION RETURN TYPE HERE I CAN TAKE VOID AS THE FUNCTION RETURN TYPE FOR THE FUNCTION FUN*/
//IN THE FUNCTION HEADER WE CAN WRITE AS FOLLOWS
void fun(int *a[])
//in the function body we can use as
a[i]=var

Resources