Passing a 2d array as a pointer C [duplicate] - c

This question already has answers here:
C, passing 2 dimensional array
(2 answers)
Closed 9 years ago.
So I have a recursive function that requires it to be of type void, without turning to global variables how can I pass a 2d array as a pointer and dereference once I edit values in the recursive function? I already tried int * m[10][10], I can't show all of the code since it is an assignment, pointers aren't required in the assignment but global variables are not permitted
Void h(int * m[10][10]){
int x = 5;
int y = 5;
*m[x][y]=7;
}
That's the general idea

Simply try this
Void h(int m[][10]) {
...
m[x][y]=7;
}
Call your function either as
h(&m[0]); // Passing the address of first row of 2D array m.
or
h(m); // As array names decays to pointer to first element of the array. Note that
// m will decays to pointer to m[0], not m[0][0].

It all depends on how you declared the array supposed to be passed to your function.
If you declared it like this
int my_array[10][10]; // array declaration
then
void fun (int m[10][10]); // prototype of a function accepting my_array
fun (my_array); // calling the function
is what you are looking for.
In that case, m is a constant pointer to 100 contiguous ints that are accessed as a 10x10 2D array.
Other possible variant:
int * my_array[10];
for (i = 0 ; i != 10 ; i++) my_array[i] = malloc (10*sizeof(int));
void fun (int m[10][]); // these syntaxes are equivalent
void fun (int * m[10]);
or this one:
int ** my_array;
my_array = malloc (10 * sizeof (int*));
for (i = 0 ; i != 10 ; i++) my_array[i] = malloc (10*sizeof(int));
void fun (int m[][]); // these syntaxes are equivalent
void fun (int * m[]);
void fun (int ** m);
or this pathological one:
int (* my_array)[10];
int a0[10];
int a1[10];
/* ... */
int a9[10];
my_array = malloc (10 * sizeof (int *));
my_array[0] = a0;
my_array[1] = a1;
/* ... */
my_array[9] = a9;
void fun (int m[][10]); // these syntaxes are equivalent
void fun (int (* m)[10]);
If your variable declaration and function prototype are not consistent, you will not access the array properly from within your function, read incoherent values, and mess up your memory and possibly crash if you attempt to modify an element.
If you have nothing better to do, you can read this little essay of mine on the subject for further details.

void h(int** m) {
int x = 5;
int y = 7;
m[x][y] = 7;
}
int main(int argc, char* argv[])
{
int** a = (int **)malloc(10*sizeof(int *));
for (int i=0; i<10; i++) {
a[i] = (int *)malloc(10*sizeof(int));
}
h(a);
return 0;
}

Related

C pass arrays by reference, malloc them and return them [duplicate]

This question already has answers here:
How to initialize and allocate a char** argument inside a function
(2 answers)
Closed 11 months ago.
I am having some issues with two arrays in C. Specifically, I pass two arrays to a function, malloc them and fill them with data and when I try to use them in my main program I get a segmentation fault.
int readData(FILE *f, int * regionSize, float **regions)
{
regionSize = (int *)calloc(10,sizeof(int));
// Fill regionSize
regions = (float **)malloc(10*sizeof(float *));
for(i=0;i<10;i++)
{
regions[i] = (float*)malloc(regionSize[i]*sizeof(float));
}
// Fill regions
// Everything prints ok here
return 0;
}
int main(int argc, char **argv)
{
int *regionSize;
float **regions;
readData(f,regionSize, regions);
printf("print------------------------\n");
for(i=0;i<10;i++)
{
for(j=0;j<userRegionsSize[i];j+=4) // SEGMENTATION FAULT HERE
{
//print
}
}
}
What am I missing?
You have a common mistake shared with many new C programmers. When you pass a pointer to a function you are copying the address held in that pointer to the argument variable. So now both the original parameter and the argument variable point to the same place.
Consider this code
int *x = malloc(sizeof(int)); // x holds the address of the newly allocated memory
*x = 5; // The memory pointed by x now has the value 5
int *y = x; // y points to the same address x points to
y = malloc(sizeof(int)); // y points to a new address in memory - note x is unchanged
What you see in the last line of code is essentially what happens when you allocate a pointer the way you did in your function - the original pointer didn't change.
To actually change the value the original pointer points to you have to pass the address of that pointer variable.
See this code
void allocate_pointers(int **array_of_ints, int ***array_of_array_of_ints)
{
int i, j;
*array_of_ints = malloc(10*sizeof(int));
*array_of_array_of_ints = malloc(10*sizeof(int*)); // Note the allocation of pointers here (not int)
for(i = 0; i < 10; ++i) {
(*array_of_ints)[i] = i;
(*array_of_array_of_ints)[i] = malloc(10*sizeof(int));
for(j = 0; j < 10; ++j)
(*array_of_array_of_ints)[i][j] = j;
}
}
int main(int argc, const char**argv)
{
int *array_of_ints;
int **array_of_array_of_ints;
allocate_pointer(&array_of_ints, &array_of_array_of_ints);
return 0;
}

Accessing an int array passed as void pointer segfaults

I'm playing with pointers and stumbled accross this problem. Like in this question I wanted a generic method signature for function foo, therefore I chose void * input as parameter. For testing reasons I casted the void pointer to an int ** pointer to use it like an 2D array.
#include <stdio.h>
#include <stdlib.h>
void * foo(void *input, size_t mySize)
{
for (size_t i = 0; i < mySize; ++i)
{
for (size_t j = 0; j < mySize; ++j)
{
((int **)input)[i*mySize][j] = 10*i+j;
}
}
return input;
}
int main(int argc, char const *argv[])
{
size_t const mySize = 10;
void * myMemory, * testPtr;
myMemory = malloc(mySize * mySize * sizeof(int));
testPtr = foo(myMemory, mySize);
free(testPtr);
return 0;
}
Now I thought that using the [] operator would be same as adding an int to the pointer, e.g. that ((int **)input[i][j] would be the same like `((int **)input)+i+j
But accessing the input array in foo segfaults and using gdb shows me
(gdb) p ((int **)input)[i][j]
Cannot access memory at address 0x0
(gdb) p ((int **)input)+i+j
$25 = (int **) 0x405260
so obviously there is a difference. And therefore I'm confused.
While arrays and pointers are similar, they are not the same.
An array - single or multi dimensional - depicts a continuous chunk of memory, containing a specific datatype. For exampleint arr [10] declares arr as 10 continuous ints in memory. int multi_arr[5][10] declares multi_arr as 5 arrays of 10 continuous ints in memory.
Furthermore, the name arr would be the base address of this array, and passing it to a function would be the same as passing &arr[0].
But this is where the similarities end. A multi dimensional array can't (technically) be cast to a pointer-to-a-pointer and then back again.
If arr above pointed to a block of ints, then dereferencing the first dimension of int ** ptr would lead you to a block of pointers toint. Dereferencing that would not take you deeper into that block, as a multi dimensional array would, rather it could point anywhere.
You allocated a one dimension array with mySize*mySize elements.
int** is an array of pointers to int, what you want is
int **array2d;
int *p;
array2D = malloc(ROWS * sizeof(int*) + ROWS * COLUMNS * sizeof(int));
p = (int*) &array2d[ROWS];
for (size_t i = 0; i < ROWS; ++i)
array2d[i] = &p[i * COLUMNS];
now array2d[row][column] can work.
Or, as already suggested, use a one dimension array and use the array[row * COLUMNS + column] formulae.

The purpose of a triple pointer in C [duplicate]

This question already has answers here:
Triple pointers in C: is it a matter of style?
(5 answers)
Closed 4 years ago.
While I have seen some threads on this, I fail to understand the meaning behind triple pointers, since it seems that it's possible to do the same without them.
void Reading(int *N, int ***M) {
printf("Input an integer N: \n");
scanf("%d", N);
*M = malloc(N * sizeof(int*));
int i;
for (i = 0; i < N; i++)
*(*M+i) = malloc(N * sizeof(int));
printf("Input N*N integers that will form a matrix \n");
int i, j;
for (i = 0; i < *N; i++)
for (j = 0; j < *N; j++)
scanf("%d", &((*M)[i][j]));
}
This code makes **M a 2D array. If I take the malloc procedures and put them into main, the triple pointer isn't needed anymore. Could someone please explain why this is the case ?
If I take the malloc procedures and put them into main, the triple pointer isn't needed anymore.
There are two ways to pass a variable to a function: either by value or by reference. When you pass the reference of a variable, that allows you to modify it.
Example:
void fun(int a) {
a = 42; // Does nothing
}
int b = 9;
fun(b);
// b is unchanged.
void fun(int *a) {
*a = 42;
}
int b = 9;
fun(&b);
// b equals 42.
Your variable happens to be a of type int **, when you pass the address (reference) of this variable, this makes it a int ***.

Passing an array created from fscanf into a new function

I have successfully fscanf a text file and saved in to an array E2N1. I am trying to pass this into a function as a pointer but it is not working. Whenever I try to call E2N1[0][0], it says that E2N is neither an array or a pointer. I've been looking all over for a solution on this.
(Sorry E2N was meant to be E2N1)
I use fscanf as:
int E2N1[noz.rowE2N][Q.N];
FILE* f = fopen("E2N.txt", "r");
for(i=0; i<noz.rowE2N; i++){
for (j=0; j<Q.N; j++){
fscanf(f,"%d",&E2N1[i][j]);
}
fscanf(f,"\n");
}
fclose(f);
and again I can't pass E2N1 into function.
Your help will be greatly appreciated.
The function is:
double *dudtF = stiffness(&U, &massM, &noz, &newV, &E2N1, &I2E, &B2E, &PP, &QQ);
and I write the function header as:
double *stiffness(double *U, double *massM, MESH *meshN, double *V1, int *E2N1, int *I2E, int *B2E, ordApprox *pp, ordApprox *qq)
V1, I2E, B2E are three arrays and I'm trying to do the same with them as I am trying to do with E2N1.
The funny thing about arrays is that they actually act as pointers.
if you have array char a[3] the variable is equivalent to char* p the same way if you have array char b[3][4] the variable b is equivalent to char** q. In other words, you should consider changing the handling in the method to take reference to reference (and possibly once more to reference) to integer.
Try google... here are some results I've got.
http://www.dailyfreecode.com/code/illustrate-2d-array-int-pointers-929.aspx
http://www.cs.cmu.edu/~ab/15-123S09/lectures/Lecture%2006%20-%20%20Pointer%20to%20a%20pointer.pdf
You don't need to pass as &E2N1, just pass as E2N1 no & as array name itself translates to pointer.
double *dudtF = stiffness(&U, &massM, &noz, &newV, E2N1, &I2E, &B2E, &PP, &QQ);
Also, you need to take it as int ** as its 2-dimensional array.
double *stiffness(double *U, double *massM, MESH *meshN, double *V1, int **E2N1, int *I2E, int *B2E, ordApprox *pp, ordApprox *qq)
Here is the example how to transfer matrix from one function to another ...
void foo (int **a_matrix)
{
int value = a_matrix[9][8];
a_matrix[9][8] = 15;
}
void main ()
{
#define ROWS 10
#define COLUMNS 10
int **matrix = 0;
matrix = new int *[ROWS] ;
for( int i = 0 ; i < ROWS ; i++ )
matrix[i] = new int[COLUMNS];
matrix[9][8] = 5;
int z = matrix[9][8] ;
foo (matrix);
z = matrix[9][8] ;
}
You cannot reference a multi-dimensional array passed to a function by point referencing as in the following:
int iVals[10][10];
foo(iVals);
void foo(int** pvals)
{
// accessing the array as follows will cause an access violation
cout << pvals[0][1]; // access violation or unpredictable results
}
You will need to specify the second dimension to the array in the function prototype
for example:
foo(int ivals[][10])
{
cout << ivals[0][1]; // works fine
}
If do not know the dimensions, then I would suggest you follow the principles outlined here:
void foo(int *p, int r, int c)
{
for(int i=0; i<r; i++)
{
for(int j=0; j<c; j++)
{
printf("%d\n", p[i*c+j]);
}
}
}
int c[6][6];
// pointer to the first element
foo(&c[0][0], 6, 6);
// cast
foo((int*)c, 6, 6);
// dereferencing
foo(c[0], 6, 6);
// dereferencing
foo(*c, 6, 6);
I hope this helps.
Alternatively you could use SAFEARRAY - see:
http://limbioliong.wordpress.com/2011/06/22/passing-multi-dimensional-managed-array-to-c-part-2/

Function Pointer Array in C

I want to make a function pointer array and be able to call them in a for-loop. How can I achieve this? I have tried:
void (**a) (int);
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for ( i = 0; i < 3; i++){
a[0]();
(*a[0])(); // Neither does work
}
But I am missing some syntax I guess:
error: too few arguments to function ‘*(a + (long unsigned int)((long unsigned int)i * 8ul))’
The function you declare is expected to take an int as a parameter:
a[0](1);
Also note that you declare a pointer to pointer for the functions, but you don't allocate any memory for them (I assume this is only in the example) Otherwise it should probably be:
void (*a[3]) (int);
You are declaring that a is a pointer to a pointer to (or an array of pointers to) a function that takes an int as a parameter - so you need to pass an int when you call the functions, e.g. a[0](42);.
I guess the below code is what you need.
typedef void * func_pointer(int);
func_pointer fparr[10];
for(int i = 0; i<10; i++)
{
fparr[i](arg); //pass the integer argument here
}
1) Where have you allocated or defined array to store function addresses?
2) in loop you are always calling (*a[0])();,There should be loop counter
You forgot to give an argument to your function.
void (**a) (int); // here it takes an int argument
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for ( i = 0; i < 3; i++){
a[0](); // here you do not give an argument
}
But be careful, you do not allocate memory to your a array, and it fails with a nice segmentation fault error.
void my_func1(int i) {
;
}
void my_func2(int i) {
;
}
void my_func3(int i) {
;
}
int main() {
void (**a) (int);
a = malloc(3*sizeof(void*)); // allocate array !
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for (int i = 0; i < 3; i++){
a[i](1); // respect your own function signature
}
free(a); // it's always a good habit to free the memory you take
return 0;
}
You can typedef void (*pfun)(int); and then pfun a[3]; is the array you want.
The following code may work for you:
typedef void (*pfun)(int);
int main() {
pfun a[3];
a[0] = myfunc1; // or &myfunc1 whatever you like
a[1] = myfunc2;
a[2] = myfunc3;
}
You can define your function-array with the needed size and initialize it with your functions like:
void my_func1(int x){}
void my_func2(int x){}
void my_func3(int x){}
void (*a[])(int)={my_func1,my_func2,my_func3};
int i;
for(i=0;i<sizeof a/sizeof*a;++i)
a[i](i);
The address-operator '&' before any function-name is redundant.

Resources