Array of pointers as function argument - c

How do I feed an array of pointers as an argument to a function?
In the code below, if I want my function f to take an array of pointers int *x[], how should I declare x in main() and feed it as argument to f?
void f(int *x[]){
int data[5] = {1,2,3,4,5};
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
int main(){
int *(x[]), k, l=5;
f(x); // this does not work
for(k=0; k<l; k++){
printf("x[%d] = %d\n", k, *x[k]);
}
}
return 0;
}
Writing f(x) does not work, and neither does f(x[]) or f(x[5]).
In fact, the declaration int *(x[]) is already not recognized by my compiler, while I thought that one could declare an array of pointers without specifying the length of the array.

In main, change
int *(x[])
to
int *x[SIZE]; // SIZE is array size
Note that, you can't declare a zero size array in C except when it is a last member of a structure.
After all, your code will invoke undefined behavior because the variable data is an automatic local variable and will not exist after function returns.
You may want this:
void f(int *x[]){
int *data = malloc(5*sizeof(int);
int temp[5] = {1,2,3,4,5};
memcpy(data, temp, 5*sizeof(int));
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}

First of all your code has no sense because you are trying to fill an array of pointers that will point to local variables. That is after exiti8ng the function all pointers will be invalid because original objects will be already destroyed.
The code could have a sense if the array in the function would have static storage duration
void f(int *x[]){
static int data[5] = {1,2,3,4,5};
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
In main array x should be defined at least as
int * x[5];
int main(){
int * x[5], k;
f(x);
for ( k=0; k < 5; k++ ){
printf("x[%d] = %d\n", k, *x[k]);
}
}
return 0;
}

An alternate way to declare an array of pointer as a parameter is to use a pointer of pointer
void f(int **x, int size){
//code
}
However, you'll have to pass the size as a second argument if you want to avoid an overflow.
To call the code you'll just have to do something like this :
int *a[] = { NULL, NULL, NULL};
f(a, 3);

Related

Double pointer to function [duplicate]

This question already has answers here:
Why can't we use double pointer to represent two dimensional arrays?
(6 answers)
Closed 7 years ago.
I know it's very basic but I MUST understand the concept, why it doesn't work?
void printMat(int arr[N][N], int n)
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (i < j)
{
arr[i][j] = 0;
}
{
arr[i][j] = i+j+2;
}
}
int** triDown(int arr[N][N], int n)
{
int i, j, **a;
for(i = 0; i < n; i++)
{
*(a+i) = (int*)malloc(sizeof(int)*(i+1));
}
for(i=0;i<n;i++)
for(j=0;j<i+1;j++)
{
a[i][j] = arr[i][j];
}
return a;
}
void main()
{
int *arr[N],**NewMat;
printMat(arr,N);
NewMat = triDown(arr,N);
}
I'm having a really hard time trying to understand the pointer-to-pointer thing when it comes to functions and dynamic allocations.
What should've been done in NewMat func?
int a[N][N] and int *a[N] are never compatible. The first is a two-dimensional array of int values, while the second is a one-dimensional array of int pointers. You need to declare it as int (*a)[N] for a compatible pointer type. Then you can pass it an int a[N][N] as an argument, just as you would in the one-dimensional case where you pass an int a[N] to an int *a.
But you need to declare the actual array in main, not just a pointer to it. Note that int (*a)[N] is only a single pointer value, so its size will most likely be 4 or 8 depending on your architecture.

Is "reformat" of multi-dimensional array by pointer to incomplete array type allowed in C?

Consider following declaration:
int a[M][N]; // M and N are known compile-time
Would it be legal to treat it like as it was declared as:
int a[N][M];
or even:
int a[A][B]; // where A * B = M * N
in C without breaking its rules (badly)?
I found that it can be acomplished without any cast:
#include <stdio.h>
void print_array(int a[][2], int n);
int main(void)
{
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
//int (*p1)[2] = a; // compile error
int (*ptr_temp)[] = a; // pointer to array of incomplete type
int (*p2)[2] = ptr_temp; // compiles without any warning
print_array(p2, 3);
}
void print_array(int a[][2], int n)
{
for (int i = 0; i < n; i++)
for (int j = 0; j < 2; j++)
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
}
Notice that we cannot assign a to p1 pointer directly. However compiler does not complain when p2 is assigned with ptr_temp even if it seems to be potentially dangerous (it does not require any cast for that). Is it really sanitized? If so, then why it disallows the first assignmment?
The behavior you see is because of the way multidimensional arrays are handled in C.
Have a look at this question Pointer address in a C multidimensional array

How to pass address of 2-d array to a double pointer which (**a) [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Passing a pointer representing a 2D array to a function in C++
I am trying to pass my 2-dimensional array to a function through pointer and want to modify the values.
#include <stdio.h>
void func(int **ptr);
int main() {
int array[2][2] = {
{2, 5}, {3, 6}
};
func(array);
printf("%d", array[0][0]);
getch();
}
void func(int **ptr) {
int i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
ptr[i][j] = 8;
}
}
}
But the program crashes with this. What did I do wrong?
Your array is of type int[2][2] ("array of 2 array of 2 int") and its name will decay to a pointer to its first element which would be of type int(*)[2] ("pointer to array of 2 int"). So your func needs to take an argument of this type:
void func(int (*ptr)[2]);
// equivalently:
// void func(int ptr[][2]);
Alternatively, you can take a reference to the array type ("reference to array of 2 array of 2 int"):
void func(int (&ptr)[2][2]);
Make sure you change both the declaration and the definition.
It crashes because an array isn't a pointer to pointer, it will try reading array values as if they're pointers, but an array contains just the data without any pointer.
An array is all adjacent in memory, just accept a single pointer and do a cast when calling the function:
func((int*)array);
...
void func(int *ptr) {
int i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
ptr[i+j*2]=8;
}
}
}

Print a square matrix using pointers

I've browsed to previously answered questions regarding pointers and matrices, but in these cases the matrices were seen as pointers to pointers. However, I am trying to create a function which read a matrix using a simple pointer and another function which prints it.
This is my code, the read functions seems to work properly, but the program crashes at the printing part. If I remove the "*" from the printf statement the program works(i.e. it prints numbers from 4 to 4- I suppose this is alright, since an int is stored on 4 bytes).
void readm(int *p,int n)
{
p=(int *)malloc(sizeof(int)*n*n);
for(int i=0;i<n*n;i++)
scanf("%d",p+i);
}
void printm(int *p,int n)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d ",*(p+(i*n)+j));
printf("\n");
}
}
In the readm function you have a problem with this line:
p=(int *)malloc(sizeof(int)*n*n);
Here you assign only to your local copy of the pointer. The variable you use when calling readm will not be changed.
You need to pass the pointer "by reference":
void readm(int **p,int n) /* Note pointer-to-pointer for `p` */
{
*p=malloc(sizeof(int)*n*n); /* Note pointer-dereference of `p` */
for(int i=0;i<n*n;i++)
scanf("%d",*p+i); /* Note pointer-dereference of `p` */
}
You then have to call the function using the address-of operator:
int *p;
readm(&p, X); /* Note use of address-of operator */
A pointer to a 1D array is defined as such:
int *p1dArr;
A pointer to a 2D array is defined as such:
int **p2dArr;
You're using a 1D array as though it's a 2D array. This is probably the source of your troubles. Change you function definitions to the following:
void readm(int **p, int row, int col)
{
p = malloc(row * sizeof(*p));
for(int r = 0; r < row; r++)
p[r] = malloc(col * sizeof(**p))
for(int r = 0; r < row; r++)
for(int c = 0; c < col; c++)
scanf("%d", &p[r][c]);
}
void printm(int **p, int row, int col)
{
for(int r = 0; r < row; r++)
{
for(int c = 0; c < col; c++)
printf("%d ", p[r][c]);
printf("\n");
}
}
The problem is that the calling code that calls function readm doesn't know that inside the function variable p (defined as a parameter of the function) got a new value. p is a local variable of the function and its life ends after exiting the function.
You should define the function the following way
void readm( int **p, int n )
{
*p = (int *)malloc( sizeof(int ) * n * n);
for ( int i=0; i<n*n; i++ ) scanf( "%d", *p+i );
}
and call it as
int *p;
readm( &p, n );
As for function printmthen there is no any need to redeclare it as
void printm( int **p, int n )
because it does not change the pointer. The only thing I would change is adding qualifier const
void printm( const int *p, int n );

create a pointer to a 2D array

I have a
bool array[size][size]
and want to pass a pointer of it to a function to change its value.
void change_to_true(???, int i, int j) { // don't know what type it should be
array[i][j] = 1;
}
How do I create a pointer of the array, and how should I pass the pointer to the function so
that I can change its value? BTW it's c code.
Thanks
Edit:
I tried
static bool array[size][size];
bool (*array_t)[index] = array;
void change_to_true(bool array, int i, int j);
Compiler told me subscripted value is neither array nor pointer
I tried to change the type definition of the function parameter from bool array to bool* array, still not work.
I also tried bool (*array_t)[][size] = &array and bool (*array_t)[size][size] = &array; for the pointer, still not work.
Also since the size of the array is decided during the runtime, I can't have a enum or a global array defined that way.
This should work:
void change_to_true(bool** array, int i, int j)
Simple solution — but no pointer to 2D array
The function should be simply:
#include <stdbool.h>
enum { size = 24 };
extern void change_to_true(bool array[][size], int i, int j);
void change_to_true(bool array[][size], int i, int j)
{
array[i][j] = true;
}
int main(void)
{
bool array[size][size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
array[i][j] = false;
change_to_true(array, i, j);
}
}
}
I'm assuming, of course, that you have a C99 or C2011 compiler. If you're stuck with C89, then you'll have to provide definitions for bool and true; the rest does not need to change. I'm not convinced the function call is worth it, compared with the assignment of false.
Solution using pointer to 2D array
Note that the code above does not, strictly, create a pointer to a 2D array. If you are really, really sure that's what you want, then the notation changes:
#include <stdbool.h>
enum { size = 24 };
extern void change_to_true(bool (*array)[][size], int i, int j);
void change_to_true(bool (*array)[][size], int i, int j)
{
(*array)[i][j] = true;
}
int main(void)
{
bool array[size][size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
array[i][j] = false;
change_to_true(&array, i, j);
}
}
}
There's no benefit to using a formal 'pointer to array' that I can think of, though — not in this context.
Solution using C99 variable length arrays
In C99, you can also use a VLA — variable length array — like this:
#include <stdbool.h>
extern void change_to_true(int size, bool array[][size], int i, int j);
void change_to_true(int size, bool array[][size], int i, int j)
{
array[i][j] = true;
}
int main(void)
{
for (int size = 2; size < 10; size++)
{
bool array[size][size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
array[i][j] = false;
change_to_true(size, array, i, j);
}
}
}
}
Note that the size must precede the array declaration in the function declaration. And yes, you also write this with pointer to array notation (actually, I edited the pointer to array notation code first, then realized that I wanted the simpler version).
Which to use?
Unless you have compelling reasons not mentioned in the question, the first version is the code to use.
This should answer you question.
In short, you make a pointer to the first element and then pass it around.
[EDIT] C supports bool since C 99
Besides that, by declaring it that way, the actual array is a pointer to a memory zone with all the size^2 instances. This means that you can pass array to change it in the function, and in your header declare that you are receiving bool array[][].
That way it should work.

Resources