pointer to pointer as 2d array - c

My background is Java therefore I'm not used to pointers, the following code throws error and I can't see way:
#include <stdio.h>
#define DIM 2
void sort_intervals(int** intervals, int n);
int main()
{
int a[3][DIM] = {
{1, 6} ,
{4, 9} ,
{3,17} };
sort_intervals(a, 3);
return 0;
}
void sort_intervals(int** intervals, int n)
{
printf("%d ", intervals[0][0]);//<--- error here
}
Error: Access violation reading location
I'm not allowed to change the function signiture

Then you need an array of pointers that point to arrays.
int a_1[DIM] = {1, 6};
int a_2[DIM] = { ... };
int a_3[DIM] = { ... };
int *a[3] = { a_1, a_2, a_3, }; // array of 3 pointers
sort_intervals(a, 3);
or exactly equivalent using compound literals you can:
int *a[3] = { (int[DIM]){1, 6}, (int[DIM]){2, 7}, (int[DIM]){3, 17}};
sort_intervals(a, 3);
even:
sort_intervals((int*[3]){
(int[DIM]){1, 6},
(int[DIM]){2, 7},
(int[DIM]){3, 17},
}, 3);

I am assuming you can change main function.
You could also initialize a as double pointer such as:
int **a = (int**)calloc(3, sizeof(int*)); //setting a as array of 3 pointers
for (int i = 0; i < 3; i++)
*a = (int*) calloc(DIM, sizeof(int)); //assigning pointer to a[0], a[1] and a[2]
Here a is array of 3 integer pointers. a[0],a[1] and a[2] are int pointers.
You can modify a as a[0][0] = 5;

If you can't change the signature as you explained in your comment, then you can get it done using a jagged array:
#define DIM 2
void sort_intervals(int** intervals, int n);
int main()
{
int **a = malloc(3 * sizeof(int*));
for (int i = 0; i < 3; i++) {
a[i] = malloc(DIM * sizeof(int));
}
a[0][0] = 1; a[0][1] = 6;
a[1][0] = 4; a[1][1] = 9;
a[2][0] = 3; a[2][1] = 17;
sort_intervals(a, 3);
for (int i = 0; i < 3; i++) {
free(a[i]);
}
free(a);
return 0;
}
void sort_intervals(int** intervals, int n)
{
printf("%d ", intervals[2][0]);//<--- error here
}

Related

How to pass pointer of arrays to functions

With my programm I try to change the order of numbers in the int array. To the first function, I just passed both arrays and printed the array called arraytemp with the changed order. After that I printed in the main function the same array, just to see if the array was filled too. I havented used any pointers in the first function - how did the array got filled? Does the arrays adress get passed to functions anyway?
Then I wanted to pass arrays with the same content to the second function, but this time I used pointers. I have no clue, how to get the same result printed, because I get a stack smashing error. I am kinda comfused with '*' and '&'. So, how should I pass these arrays when using pointers?
#include <stdio.h>
void switchnum (int arraytemp[6], int array[], int laenge) {
printf("\n\nAfter (in function 1):\n");
for(int i = 0 ; i<laenge ; i++) {
arraytemp[i] = array[laenge-1-i];
printf("%d ", arraytemp[i]);
}
return 0;
}
void switchnum2 (int *arraytemp2[6], int array2[], int laenge2) {
printf("\nAfter (in function2):\n");
for(int j = 0 ; j<laenge2 ; j++) {
arraytemp2[j] = array2[laenge2-1-j];
printf("%d ", arraytemp2[j]);
}
return 0;
}
int main() {
int array[] = {4,8,1,3,0,9};
int arraytemp[6];
printf("Before (main):\n");
for(int i = 0 ; i<6 ; i++) {
printf("%d ", array[i]);
}
switchnum(arraytemp, array, 6);
printf("\nAfter (in main):\n");
for(int i = 0 ; i<6 ; i++) {
printf("%d ", arraytemp[i]);
}
int array2[] = {4,8,1,3,0,9};
int arraytemp2[6];
switchnum2(arraytemp2, array2, 6);
return 0;
}
The compiler adjusts a parameter having an array type to pointer to the array element type.
So this function declaration
void switchnum (int arraytemp[6], int array[], int laenge);
is equivalent to the following declaration
void switchnum (int arraytemp[], int array[], int laenge);
and the same way is equivalent to the following declaration
void switchnum (int *arraytemp, int *array, int laenge);
As for this function declaration
void switchnum2 (int *arraytemp2[6], int array2[], int laenge2);
then it is adjusted by the compiler to the declaration
void switchnum2 (int **arraytemp2, int *array2, int laenge2);
So the used argument expression and the function parameter have incompatible pointer types.
Pay attention to that in this call
switchnum(arraytemp, array, 6);
the both arrays are converted to pointers to their first elements of the type int *.
In fact this call is equivalent to
switchnum( &arraytemp[0], &array[0], 6);
How to pass pointer of arrays to functions
In this case you are trying to pass an array of pointers to a function and not a pointer of arrays:
void switchnum2(
int* arraytemp2[6], int array2[], int laenge2)
Maybe it helps to see the output of this example program, as it shows the output of many of your cases
Example
#include <stdio.h>
void test_arr(int*[6]);
int main(void)
{
int array[] = {4, 8, 1, 3, 0, 9};
int* pArr[6] = {0}; // 6 pointers to int
printf("original vector in main(): ");
for (int i = 0; i < 6; i += 1) printf("%d ", array[i]);
printf("\n");
for (int i = 0; i < 6; i++) pArr[i] = &array[i];
test_arr(pArr);
printf("\nIn main() &array[0] = %p\n", &array[0]);
return 0;
}
void test_arr(int* pInt[6])
{
printf("In test_array(): ");
for (int i = 0; i < 6; i += 1)
printf("%d ", *pInt[i]);
printf("\n");
int* myP = *pInt;
printf("*pInt\tpoints to value %d\n", *myP);
myP = pInt[0];
printf("pInt[0]\tpoints to value %d\n", *myP);
int x = *pInt[0];
printf("*pInt[0] = %d\n", x);
printf("\ntest_array() &pInt[0] = %X\n", pInt[0]);
return;
}
output
original vector in main(): 4 8 1 3 0 9
In test_array(): 4 8 1 3 0 9
*pInt points to value 4
pInt[0] points to value 4
*pInt[0] = 4
test_array() &pInt[0] = 197BFB00
In main() &array[0] = 000000CF197BFB00
Your program with some changes in the functions
I changed some lines in your code to get the expected result
#include <stdio.h>
void switch1(const int[],int[],const int);
void switch2(const int[],int*[],const int);
void show_array(const int[6],const char*);
int main(void)
{
int arr_out[] = {0,0,0,0,0,0};
show_array(arr_out, "arr_out in main()");
// call 1st function
printf("switch1() uses int[] as output\n");
switch1((int[6]){6, 5, 4, 3, 2, 1}, arr_out, 6);
show_array(arr_out, "arr_out using 6..1 array as input and 1st function");
// for 2nd function we need an array of pointers
int* pArr[6] = {0}; // 6 pointers to int
for (int i = 0; i < 6; i++) pArr[i] = &arr_out[i];
printf("switch2() uses int*[] as output\n");
switch2((int[6]){1, 2, 3, 4, 5, 6}, pArr, 6);
show_array(arr_out, "arr_out using 1..6 array as input and 2nd function");
return 0;
}
void switch1(const int in[], int out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
out[i] = in[laenge - 1 - i];
}
void switch2(const int in[], int* out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
*out[i] = in[laenge - 1 - i];
}
void show_array(const int array[6], const char* msg)
{
printf("%s:\t", msg);
for (int i = 0; i < 6; i++) printf("%d ", array[i]);
printf("\n");
}
output of the modified code
arr_out in main(): 0 0 0 0 0 0
switch1() uses int[] as output
arr_out using 6..1 array as input and 1st function: 1 2 3 4 5 6
switch2() uses int*[] as output
arr_out using 1..6 array as input and 2nd function: 6 5 4 3 2 1
about the changes
void show_array(const int array[6], const char* msg)
{
printf("%s:\t", msg);
for (int i = 0; i < 6; i++) printf("%d ", array[i]);
printf("\n");
}
This function is a helper to show the array contents and accepts a title. Very convenient here
the 2 functions has no output (printf() calls)
parameters are declared const so we can build the vector at the function call
I am using shorter names and changed the order of arguments to input and then output
void switch1(const int in[], int out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
out[i] = in[laenge - 1 - i];
}
void switch2(const int in[], int* out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
*out[i] = in[laenge - 1 - i];
}
Here you see the difference between the 2 functions: a single asterisk.
But in order of using the second function you need to build the vector of pointers as here
// call 1st function
printf("switch1() uses int[] as output\n");
switch1((int[6]){6, 5, 4, 3, 2, 1}, arr_out, 6);
show_array(arr_out, "arr_out using 6..1 array as input and 1st function");
// for 2nd function we need an array of pointers
int* pArr[6] = {0}; // 6 pointers to int
for (int i = 0; i < 6; i++) pArr[i] = &arr_out[i];
printf("switch2() uses int*[] as output\n");
switch2((int[6]){1, 2, 3, 4, 5, 6}, pArr, 6);
show_array(arr_out, "arr_out using 1..6 array as input and 2nd function");

C - Double pointer array - not getting correct values

Context
I created this simple code where I store various arrays in my_arrays() function and different functions (in my example the main()) can get the hard-coded arrays via the function my_arrays().
See the code here:
#include <stdio.h>
int my_arrays(int *size, int **arrays) {
size[0] = 3;
int array_1[3] = {1, 2, 3};
arrays[0] = array_1;
size[1] = 5;
int array_2[5] = {2, 3, -5, 7, 11};
arrays[1] = array_2;
}
int main() {
int num_of_arrays = 2;
int sizes[2];
int *arrays[2];
my_arrays(sizes, arrays);
for (int i=0; i < num_of_arrays; i++) {
int *array = arrays[i]; // point to sub-array
int size = sizes[i];
printf("array[%d]: {", i);
for (int x=0; x < size; x++) {
printf(" %d", array[x]);
}
printf(" }\n", i);
}
return 0;
}
In the main() I then loop through the sub-arrays and loop through each individual number and print it out.
What I expect the code above to print out is:
array[0]: { 1 2 3 }
array[1]: { 2 3 -5 7 11 }
But when compiling and running I get this:
array[0]: { 1993067712 1617605192 -2 }
array[1]: { 3936256 8 6422188 7 6422476 }
Why?
In my_arrays, array_1 and array_2 are local arrays on the stack. They will be invalid as soon as you return from my_array. Now arrays[0] and arrays[1] hold pointers to invalid or "stale" memory. Accessing that is undefined behaviour.
(The garbage values you see shows you that your arrays have been overwritten by other uses of the stack space, probably by calls to printf.)
If you want to create arrays, you can allocate memory on the heap:
int my_arrays(int *size, int **arrays)
{
size[0] = 3;
arrays[0] = malloc(3 * sizeof(int));
arrays[0][0] = 1;
arrays[0][1] = 2;
arrays[0][2] = 3;
// ... initialize other arrays ...
return 0;
}
You should explicitly free it after you're done using it:
// at the end of main
for (int i=0; i < num_of_arrays; i++) {
free(arrays[i]);
}

Matrix product cause error: subscripted value is neither array nor pointer nor vector

I have a Java method that multiplies 2 matrices. I have tried to port the same method in C without success.
Here is my attempt to write a method that should multiply 2 matrices in C:
float **multiply(int m1, int n1, float Xy1[], int m2, int n2, float Xy2[]) {
int i, j, k;
float **result = allocate_mem_mtrx(m1, n2);
for (i = 0; i < m1; i++) {
for (j = 0; j < n2; j++) {
for (k = 0; k < n1; k++) {
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
At this line
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
I receive the error:
subscripted value is neither array nor pointer nor vector
Clearly my syntax is wrong, but I haven't understood how I should fix this line of code, to solve my problem.
In my main I have:
float matrix1[3][2] = {{0, 1}, {3, 4}, {6, 7}};
float matrix2[2][3] = {{5, 1, 2}, {3, 4, 5}};
with the actual signature I invoke the method in this way:
multiply(3, 2, &matrix1, 2, 3, &matrix2);
My original Java method
public static int[][] multiply(int[][] Xy1, int[][] Xy2) {
int rowsInXy1 = Xy1.length;
int columnsInXy1 = Xy1[0].length; // same as rows in B
int columnsInXy2 = Xy2.length;
int[][] result = new int[rowsInXy1][columnsInXy2];
for (int i = 0; i < rowsInXy1; i++) {
for (int j = 0; j < columnsInXy2; j++) {
for (int k = 0; k < columnsInXy1; k++) {
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
You have float Xy1[]
but you treat it as 2D
Xy1[i][k]
Same for Xy2.
You should change float Xy1[] to float** Xy1.
Also another thing, in your loop I feel that you are sure that result 2D array is initialized in your function that says allocate. If that functions just mallocs the array, then this array will have garbage inside.
For more.
[EDIT]
Also I see in one other answer that they cast what malloc returns. Ouch!
Do not cast the return value of malloc in C.
[EDIT.2]
SO, you could something like this:
#include <stdlib.h>
// We return the pointer
float **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
float **table;
table = malloc(N*sizeof(float *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(float) );
return table;
}
void free2Darray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
// do not forget to FREE what multiply returns
float **multiply(int m1, int n1, float** Xy1,int m2, int n2, float** Xy2) {
int i,j,k;
float **result = get(m1,n2);
for (i = 0; i < m1; i++) {
for (j = 0; j < n2; j++) {
for (k = 0; k < n1; k++) {
// this line is correct, the prototype of the function
// was not OK
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
int main(void) {
float** A = get(5, 5); // arrays declared as double pointers
float** B = get(5, 5);
float** C = get(5, 5);
C = multiply(5, 5, A, 5, 5, B);
// free2Darray function defined below
free2Darray(A, 5);
free2Darray(B, 5);
free2Darray(C, 5);
return 0;
}
[EDIT.3]
Another way, if you now the columns apriori, which you probably don't as your function implies, you could do that:
#include <stdlib.h>
#include <stdio.h>
// We return the pointer
float **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
float **table;
table = malloc(N*sizeof(float *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(float) );
return table;
}
float **multiply(int m1, int n1, float Xy1[][2],int m2, int n2, float Xy2[][2]) {
int i,j,k;
float **result = get(m1,n2);
for (i = 0; i < m1; i++) {
for (j = 0; j < n2; j++) {
for (k = 0; k < n1; k++) {
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
int main() {
float matrix1[2][2] = {{0, 1}, {3, 4}};
float matrix2[2][2] = {{0, 1}, {3, 4}};
float** C;
C = multiply(2, 2, matrix1, 2, 2, matrix2);
free2Darray(C, 2);
printf("ok\n");
return 0;
}
I got the get() function from my pseudo-site.
float Xy1[]
is not a two dimensional array, so to write
Xy1[i][k]
is an error.
In C you can use a pointer to pointer notation:
float** multiply( int m1, int n1, float** Xy1,int m2, int n2, float** Xy2) {
//...
}
or you can take advantage of the variable-length array feature in the C language and write
functions that can take multidimensional arrays of varying sizes:
float** multiply( int m1, int n1, float Xy1[m1][n1],
int m2, int n2, float Xy2[m2][n2]) {
float **result, i, j;
result = malloc( m1 * sizeof *result); // remember to free this memory
for( i = 0; i < m1; ++i)
result[i] = malloc( n2 * sizeof float);
//... I don't continue since there seems to be an issue with your indices
// however now you can use result this way:
// result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j]; i, j, k integers
return result;
}
In C++ use a std::vector< std::vector<float> >:
typedef std::vector<std::vector<float> > array; // shorten notation
array multiply( const array& Xy1, const array& Xy2) {
//...
}
In addition
int[][] result = new int[rowsInXy1][columnsInXy2];
is not correct way to create two dimensional array. Such array is an array of pointers and correct way to create this is:
C
int **a, i;
a = malloc( rowsInXy1 * sizeof *a);
for( i = 0; i < rowsInXy1; ++i)
a[i] = malloc( columnsInXy2 * sizeof int);
C++
int** result = new int*[rowsInXy1];
for( int i = 0; i < rowsInXy1; ++i)
result[i] = new int[columnsInXy2];
I see you have already chosen a solution but here is some additional info about arrays in C.
In C there is no equivalent of Java's int[][] type. Java array storage also includes storage of how many items are in the array. However, C's array storage is purely the values in the array contiguous in memory; and you have to keep track of the size either as compile-time constants, or by storing a variable that holds the length.
Further; originally in C, arrays (using the [] syntax) had to have their size known at compile-time. There is an optional feature called variable-length array which means that the array size can be specified at runtime -- however the size can't be changed once the array is created. The major compiler vendors all support VLA, I think.
The VLA uses contiguous storage, however it is not possible to return one via a function's return value. But you can "return" them using an "out" parameter.
It's probably going to turn into a jumble if your code sometimes uses VLAs and sometimes uses dynamically-allocated arrays of pointers.
Another point: in both cases you have to store both array dimensions separately from the array, so that's 3 variables to pass around for each matrix. I'd like to suggest wrapping all of this up in a struct. Since VLAs can't live in a struct, and the compiler might not support them anyway, your best bet may be to use the dynamic allocation version.
Even though we are in C, if you are planning to do more than just a throwaway program, my recommendation would be to use an object-oriented approach for the matrix. Here's an example framework (where all Matrices are to have the Matrix be dynamically allocated, as well as the cells):
// Matrix.h
typedef struct
{
size_t y_dim, x_dim;
float **cells;
} Matrix;
Matrix *matrix_construct(size_t y_dim, size_t x_dim);
void matrix_free(Matrix *m); // frees m as well as cells
void matrix_assign(Matrix *dst, Matrix const *src); // may re-size dst
void matrix_set_values(Matrix *dst, float *row_major);
bool matrix_is_equal(Matrix const *m1, Matrix const *m2);
typedef Matrix *MatrixBinaryOperator(Matrix const *m1, Matrix const *m2);
MatrixBinaryOperator matrix_multiply;
Example usage:
float mat1_array[3][2] = {{0, 1}, {3, 4}, {6, 7}};
float mat2_array[2][3] = {{5, 1, 2}, {3, 4, 5}};
Matrix *mat1 = matrix_construct(3, 2);
Matrix *mat2 = matrix_construct(2, 3);
matrix_set_values(mat1, (float *)&mat1_array);
matrix_set_values(mat2, (float *)&mat2_array);
Matrix *mat3 = matrix_multiply(mat1, mat2);
matrix_free(mat1);
matrix_free(mat2);
matrix_free(mat3);
See it working - disclaimer: this code doesn't check for malloc failure and I have only done the most basic testing; and a lot of optimization is possible.

Array of arrays, with different sizes

I'm having an array, that has arrays in every cell. For example, the big array is called arr:
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b}
Now the problem is, if I want to print the small arrs, inside the big array.
Here is my code:
#include <stdio.h>
void printArr(int arr [], int n)
{
for (int i = 0 ; i < n ; i++)
{
printf("%d ", *(arr + i));
}
printf("\n");
}
int main()
{
int a[5] = {1, 8, 4, 2, 0};
int b[3] = {1, 4, 2};
int *arr [2] = {a, b};
int n = 0;
for (int i = 0 ; i < 2 ; i++)
{
printArr(*(arr + i), n);
}
}
The output is supposed to be something like this:
1 8 4 2 0
1 4 2
But I can't get the size of each array, since sizeof(*(arr + i) gives me 4, which is the size of the pointer (the name of the array), and not all the array it self.
So what can I do?
Thanks!
The Problem:
The C language only provides a way of finding the size of types.
This gives the subtle differences between applying sizeof to:
1) An array of a type such as:
int a[3];
sizeof(a); // => 3 * sizeof(int)
2) A pointer to the type:
int *ptr;
sizeof(ptr); // => sizeof(int *)
or
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b};
sizeof(arr[1]); // => sizeof(int *)
Some solutions:
Store the size
As jfly proposes store the size of the arrays.
Makes finding the size a constant time operation.
Append an end marker
Adding a end marker like '\0' as used for c-style strings.
You might use INT_MAX or INT_MIN in this case.
The printArr implementation would need to change to:
void printArr(int *arr)
{
int *it = arr;
while(arr != INT_MIN);
{
printf("%d ", *it);
}
printf("\n");
}
Disadvantages:
Finding the size of the array requires iterating over the full array.
Gives the risk of an actual value colliding with the end marker value.
Advantages:
The varying sized array can be passed as a single argument.
Using iterators
Store the pointer to the first and one past the last value.
void printArr(int *begin, int *end)
{
for (int *it = begin; it != end; it++)
{
printf("%d ", *it);
}
printf("\n");
}
int *end_arr[2] = {a + 3, b + 2};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], end_arr[i]);
}
Can be extended to other data structures.
Since arr is an array of pointers, so you can't get the size of array from the pointer which points to an array, you need additional size info:
int size_arr[2] = {sizeof(a) / sizeof(int), sizeof(b) / sizeof(int)};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], size_arr[i]);
}

value of pointer to a char array vs plain char pointer

I am having a hard time understanding where I can use a pointer to an array,
e.g: char (*a)[10];.
So two basic questions.
Please give me a simple example of how just a pointer to an array can be used in C code.
Why would one use it as apposed to just declaring a variable as a pointer and then incrementing/decrementing the address after that point.
Say you have a database query that returns a set of strings. Further, say that you know that these strings are no longer than 9 characters in length. Only, you don't know how many elements are in the set returned by the query.
char (*a)[10] = malloc( NumRecords * sizeof *a );
if ( a == NULL )
{
/* Handle error appropriately */
return EXIT_FAILURE; /* Naive */
}
for ( i = 0 ; i < NumRecords ; ++i )
{
assert(strlen(DbRecordSet[i]) < 10);
strcpy(a[i], DbRecordSet[i]);
}
Example: how to print the elements of an array of num_row rows and 3 columns:
#include <stdio.h>
#define NUM_ROW(x) (sizeof (x) / sizeof *(x))
// print elements of an array of num_row rows and 3 columns
void print(int (*a)[3], size_t num_row)
{
size_t num_col = sizeof *a / sizeof **a;
for (int i = 0; i < num_row; i++) {
for (int j = 0; j < num_col; j++) {
printf("%d\n", a[i][j]);
}
}
}
int main(void)
{
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int b[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(a, NUM_ROW(a));
print(b, NUM_ROW(b));
return 0;
}
Any time you pass an expression with a multi-dimensioned array type to a function, you're going to be working with a pointer to an array:
int a[10][20];
foo(a);
void foo(int (*p)[20]) // or int p[][20]
{ ... }

Resources