i have declared a pointer to a group of 3-d array which I have shared below.I have a problem in accessing elements of the 3-d array using pointers to the 3-d array.
#include <stdio.h>
void main()
{
int m,row,col;
int *ptr,*j;
int array[2][5][2]={10,20,30,40,50,60,70,80,90,100,18,21,3,4,5,6,7,81,9,11};
int (*p)[5][2]; // pointer to an group of 3-d array
p=array;
for(m=0;m<2;m++)
{
ptr=p+m;
for(row=0;row<5;row++)
{
ptr=ptr+row;
for(col=0;col<2;col++)
{
printf("\n the vale is %d",*(ptr+col));
}
}
}
}
output:
the value is 10
the value is 20
the value is 20
the value is 30
the value is 40
the value is 50
the value is 70
the value is 80
the value is 18
the value is 21
the value is 18
the value is 21
the value is 21
the value is 3
the value is 4
the value is 5
the value is 7
the value is 81
the value is -1074542408
the value is 134513849
my question is how to access the elements of 3-d array using pointer to an array and in my case the output shows my code not accessing the elements 90,100,9,11 and how do i can access this in the above code.Thanks in advance.
Although flattening the arrays and accessing them as 1-d arrays is possible, since your original question was to do so with pointers to the inner dimensions, here's an answer which gives you pointers at every level, using the array decay behaviour.
#include <stdio.h>
/* 1 */
#define TABLES 2
#define ROWS 5
#define COLS 2
/* 2 */
int main()
{
/* 3 */
int array[TABLES][ROWS][COLS] = {
{ {10, 20}, {30, 40}, {50, 60}, {70, 80}, {90, 100} },
{ {18, 21}, {3, 4}, {5, 6}, {7, 81}, {9, 11} }
};
/* pointer to the first "table" level - array is 3-d but decays into 2-d giving out int (*)[5][2] */
/* name your variables meaningully */
int (*table_ptr)[ROWS][COLS] = array; /* try to club up declaration with initialization when you can */
/* 4 */
size_t i = 0, j = 0, k = 0;
for (i = 0; i < TABLES; ++i)
{
/* pointer to the second row level - *table_ptr is a 2-d array which decays into a 1-d array */
int (*row_ptr)[COLS] = *table_ptr++;
for (j = 0; j < ROWS; ++j)
{
/* pointer to the third col level - *row_ptr is a 1-d array which decays into a simple pointer */
int *col_ptr = *row_ptr++;
for (k = 0; k < COLS; ++k)
{
printf("(%lu, %lu, %lu): %u\n", (unsigned long) i, (unsigned long) j, (unsigned long) k, *col_ptr++); /* dereference, get the value and move the pointer by one unit (int) */
}
}
}
return 0; /* report successful exit status to the platform */
}
Inline code comments elaborated with reference
It's good practise to have the dimensions defined commonly somewhere and use it elsewhere; changing at one place changes it at all places and avoids nasty bugs
main's retrun type is int and not void
It's recommended not to avoid the inner braces
Use size_t to hold size types
Problems in your code
For the line ptr=p+m;, GCC throws assignment from incompatible pointer type; reason is p is of type int (*)[5][2] i.e. pointer to an array (size 5) of array (size 2) of integers, which is assigned to ptr which is just an integer pointer. Intead if you change it to int (*ptr) [5]; and then do ptr = *(p + m);. This is what my code does (I've named p as table_ptr), only that it doesn't use m but it increments p directly.
After this at the third level (inner most loop), you need a integer pointer say int *x (in my code this is col_ptr) which you'd do int *x = *(ptr + m1). Bascially you need to have three different pointers, each for one level: int (*) [5][2], int (*) [2] and int *. I've named them table_ptr, row_ptr and col_ptr.
Rewritten your code below and just used the pointer p to print everything.
#include <stdio.h>
void main()
{
int m,row,col;
int array[2][5][2]={10,20,30,40,50,60,70,80,90,100,18,21,3,4,5,6,7,81,9,11};
int (*p)[5][2]; // pointer to an group of 3-d array
p=array;
for(m=0;m<2;m++)
{
for(row=0;row<5;row++)
{
for(col=0;col<2;col++)
{
printf("\n the vale is %d", *((int*)(p+m) + (row*2) + col));
}
}
}
}
You can easily access all the elements simply by a looping through 2*5*2 = 20 and using a pointer to the first element of array, i.e, array[0][0][0] assuming 3D array as 1D array of arrays of arrays of int's.
#include <stdio.h>
void main()
{
int m; //row,col;
int *ptr; //,*j;
int array[2][5][2]={10,20,30,40,50,60,70,80,90,100,18,21,3,4,5,6,7,81,9,11};
//int (*p)[5][2]; // pointer to an group of 3-d array
//p=array;
ptr = &array[0][0][0];
for(m=0;m <2;m++)
{
for (m = 0; m < 20; m++)
/* ptr=ptr+m;
for(row = 0;row < 5;row ++)
{
ptr=ptr+row;
for(col=0;col<2;col++)
{
printf("\n the vale is %d",*(ptr+col));
}
}*/
printf("\n the vale is %d", *(ptr++));
}
}
I commented some parts of your code and left it in the modified code to let you clear what I have done.
#include<stdio.h>
int main()
{
int array[2][2][2]={1,2,3,4,5,6,7,8};
int *p;
p=&array[0][0][0];
int i=0,j,k;
/*Accessing data using pointers*/
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
for(k=0;k<2;k++)
{
printf("%d\n",*p);
p++;
}
}
}
return 0;
}
This is a sample code where elements in a 2X2X2 array is been accessed using pointers.
Hope it helps !!!!
Related
I have written code which allows me to modify the elements of a 1D array within my function by passing the element of the array:
I print the original array
I pass each element of the array to the function
Within the function I add the value 50 to each element of the array
I then call the function, and print out to screen the modified element value (i.e the value of each element +50)
I have been able to do this for a 1D array, with example values in the array being (10,20,30) and the valued printed after modification being (60,70,80).
What I am hoping to do is adapt that code to work for 2D arrays, you will see my attempt at doing this below. This code focuses on the use of int, but once I understand how to achieve this I am hoping to adapt for the use of a 2D string as well.
With the code below:
My objective is
Print to screen the original 2D array
Pass each element of the 2D array to the function
Within the function add the value 50 to each element of the array
Then call the function, and print out the modified element values to the screen(expected result displayed on screen 60,61,etc,.)
So far I have been able to print the original 2D array to the screen. It is the function I think I am messing up and would appreciate any advice. Thank you.
#include <stdio.h>
#include <string.h>
#define M 4
#define N 2
int function(int **arr);
int main() {
int i, a;
int arr[N][M] = {10, 11, 12, 13, 14, 15, 16, 17};
// the int array first
for(i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
// Accessing each variable
printf("value of arr[%d] is %d\n", i, arr[i][j]);
}
}
printf("\n ***values after modification***\n");
a = function(&arr[i][0]);
// int array print results
for(int i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr %d\n", arr[i][j]);
}
}
return 0;
}
int function(int **arr) {
int i;
int j;
for(int i = 0; i < 3; i++) {
for(size_t j = 0; j < 5; j++) {
arr[i][j] = arr[i][j] + 50;
}
}
}
My apologies in advance for silly mistakes I am very new to C.
Thank you in advance.
The function int function(int **arr) does not return an int so make it void.
When you call it, a = function(&arr[i][0]);, you do not use a after the assignment. I suggest that you remove a from the program completely since it's not used anywhere.
The call to the function, function(&arr[i][0]);, should simply be function(arr);
The function signature needs to include the extent of all but the outermost dimension:
void function(int arr[][M])
Inside the function, you use 3 and 5 instead of N and M. That accesses the array out of bounds.
In function, the i and j you declare at the start of the function are unused. Remove them.
arr[i][j] = arr[i][j] + 50; is better written as arr[i][j] += 50;
When initializing a multidimensional array, use braces to make it simpler to read the code:
int arr[N][M] = {{10, 11, 12, 13}, {14, 15, 16, 17}};
In main you mix int and size_t for the indexing variables. I suggest you settle for one type.
Remove unused header files (string.h)
Example:
#include <stdio.h>
#define N 2
#define M 4
void function(int arr[][M]) {
for(int i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
arr[i][j] += 50;
}
}
}
int main() {
int arr[N][M] = {{10, 11, 12, 13}, {14, 15, 16, 17}};
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
printf("\n ***values after modification***\n");
function(arr);
// int array print results
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
}
Since you print the array more than once, you could also add a function to do so to not have to repeat that code in main:
void print(int arr[][M]) {
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
}
Two-Dimensional arrays in C (and C++) are actually one-dimensional arrays whose elements are one-dimensional arrays. The indexing operator [] has left-to-right semantics, so for a type arr[N][M] the first index (with N elements) is evaluated first. The resulting expression, e.g. arr[0], the first element in arr, is a one-dimensional array with M elements. Of course that array can be indexed again , e.g. arr[0][1], resulting in the second int in the first sub-array.
One of the quirks in the C language is that if you use an array as a function argument, what the function sees is a pointer to the first element. An array used as an argument "decays" or, as the standard says, is "adjusted" that way. This is no different for two-dimensional arrays, except that the elements of a two-dimensional array are themselves arrays. Therefore, what the receiving function gets is a pointer to int arr[M].
Consider: If you want to pass a simple integer array, say intArr[3], to a function, what the function sees is a pointer to the first element. Such a function declaration might look like void f(int *intPtr) and for this example is simply called with f(intArr). An alternative way to write this is void f(int intPtr[]). It means exactly the same: The parameter is a pointer to an int, not an array. It is pointing to the first — maybe even only — element in a succession of ints.
The logic with 2-dimensional arrays is exactly the same — except that the elements, as discussed, have the type "array of M ints", e.g. int subArr[M]. A pointer argument to such a type can be written in two ways, like with the simple int array: As a pointer like void f(int (*subArrPtr)[M]) or in array notation with the number of top-level elements unknown, like void f(int arr[][M]). Like with the simple int array the two parameter notations are entirely equivalent and interchangeable. Both actually declare a pointer, so (*subArrPtr)[M] is, so to speak, more to the point(er) but perhaps more obscure.
The reason for the funny parentheses in (*subArrPtr)is that we must dereference the pointer first in order to obtain the actual array, and only then index that. Without the parentheses the indexing operator [] would have precedence. You can look up precedences in this table. [] is in group 1 with the highest priority while the dereferencing operator * (not the multiplication!) is in group 2. Without the parentheses we would index first and only then dereference the array element (which must therefore be a pointer), that is, we would declare an array of pointers instead of a pointer to an array.
The two possible, interchangeable signatures for your function therefore are
void function( int (*arrArg)[M] ); // pointer notation
void function( int arrArg[][M] ); // "array" notation (but actually a pointer)
The entire program, also correcting the problems Ted mentioned, and without printing the original values (we know them, after all), is below. I have also adapted the initialization of the two-dimensional array so that the sub-arrays become visible. C is very lenient with initializing structures and arrays; it simply lets you write consecutive values and fills the elements of nested subobjects as the come. But I think showing the structure helps understanding the code and also reveals mistakes, like having the wrong number of elements in the subarrays. I have declared the function one way and defined it the other way to show that the function signatures are equivalent. I also changed the names of the defines and of the function to give them more meaning.
#include<stdio.h>
#define NUM_ELEMS_SUBARRAY 4
#define NUM_ELEMS_ARRAY 2
/// #arrArg Is a pointer to the first in a row of one-dimensional
/// arrays with NUM_ELEMS_SUBARRAY ints each.
void add50ToElems(int arrArg[][NUM_ELEMS_SUBARRAY]);
int main()
{
// Show the nested structure of the 2-dimensional array.
int arr[NUM_ELEMS_ARRAY][NUM_ELEMS_SUBARRAY] =
{
{10, 11, 12, 13},
{14, 15, 16, 17}
};
// Modify the array
add50ToElems(arr);
// print results
for (int i = 0; i < NUM_ELEMS_ARRAY; i++) {
for (int j = 0; j < NUM_ELEMS_SUBARRAY; j++)
{
printf("value of arr[%d][%d]: %d\n", i, j, arr[i][j]);
}
}
return 0;
}
// Equivalent to declaration above
void add50ToElems(int (*arrArg)[NUM_ELEMS_SUBARRAY])
{
for (int i = 0; i < NUM_ELEMS_ARRAY; i++)
{
for (size_t j = 0; j < NUM_ELEMS_SUBARRAY; j++)
{
//arrArg[i][j] = arrArg[i][j] + 50;
arrArg[i][j] += 50; // more idiomatic
}
}
}
Why is it wrong to pass a two-dimensional array to a function expecting a pointer-to-pointer? Let's consider what void f(int *p) means. It receives a pointer to an int which often is the beginning of an array, that is, of a succession of ints lying one after the other in memory. For example
void f(int *p) { for(int i=0; i<3; ++i) { printf("%d ", p[i]); }
may be called with a pointer to the first element of an array:
static int arr[3];
void g() { f(arr); }
Of course this minimal example is unsafe (how does f know there are three ints?) but it serves the purpose.
So what would void f(int **p); mean? Analogously it is a pointer, pointing to the first in a succession of pointers which are lying one after the other in memory. We see already why this will spell disaster if we pass the address of a 2-dimensional array: The objects there are not pointers, but all ints! Consider:
int arr1[2] = { 1,2 };
int arr2[2] = { 2,3 };
int arr3[2] = { 3,4 };
// This array contains addresses which point
// to the first element in each of the above arrays.
int *arrOfPtrToStartOfArrays[3] // The array of pointers
= { arr1, arr2, arr3 }; // arrays decay to pointers
int **ptrToArrOfPtrs = arrOfPtrToStartOfArrays;
void f(int **pp)
{
for(int pi=0; pi<3; pi++) // iterate the pointers in the array
{
int *p = pp[pi]; // pp element is a pointer
// iterate through the ints starting at each address
// pointed to by pp[pi]
for(int i=0; i<2; i++) // two ints in each arr
{
printf("%d ", pp[pi][i]); // show double indexing of array of pointers
// Since pp[pi] is now p, we can also say:
printf("%d\n", p[i]); // index int pointer
}
}
}
int main()
{
f(ptrToArrOfPtrs);
}
f iterates through an array of pointers. It thinks that the value at that address, and at the subsequent addresses, are pointers! That is what the declaration int **pp means.
Now if we pass the address of an array full of ints instead, f will still think that the memory there is full of pointers. An expression like int *p = pp[i]; above will read an integer number (e.g., 1) and think it is an address. p[i] in the printf call will then attempt to access the memory at address 1.
Let's end with a discussion of why the idea that one should pass a 2-dimensional array as a pointer to a pointer is so common. One reason is that while declaring a 2-dimensional array argument as void f(int **arr); is dead wrong, you can access the first (but only the first) element of it with e.g. int i = **arr. The reason this works is that the first dereferencing gives you the first sub-array, to which you can in turn apply the dereferencing operator, yielding its first element. But if you pass the array as an argument to a function it does not decay to a pointer to a pointer, but instead, as discussed, to a pointer to its first element.
The second source of confusion is that accessing elements the array-of-pointers uses the same double-indexing as accessing elements in a true two-dimensional array: pp[pi][i] vs. arr[i][j]. But the code produced by these expressions is entirely different and spells disaster if the wrong type is passed. Your compiler warns about that, by the way.
Can we directly insert a 1D array to a 2D array?
For example I have this code:
void insert(int[]data , int**collection)
{
collection[1] = data
}
int main()
{
int data[2]= {1,3}
int collection[2][2];
insert(data,&collection);
}
Will this work?
You cannot insert a 1D array to 2D array the way you are doing. Use memcpy to copy the elements of 1D array to 2D array, like this:
memcpy(collection[1], data, 2 * sizeof(int));
this will copy the 2 integer elements of data array to collection[1].
Besides, a couple of problems in your code. Lets discuss them:
First:
insert(data,&collection);
^
You don't need to pass the address of collection. Note that, an array, when used in an expression, will convert to pointer to its first element (there are few exceptions to this rule). That means, when you pass collection, it will convert to type int (*)[2]. Just do:
insert(data, collection);
Second:
void insert(int[]data , int**collection)
int[]data is wrong. The first parameter of insert() should be int data[2] or int data[], both are equivalent to int * data. You can use either of them.
The second argument to insert() is collection array which is a 2D array of integers. When you pass it to insert(), it will decay to pointer whose type is int (*)[2]. The type of second parameter of insert() is int ** which is not compatible with the argument that you are passing to insert() function. The second parameter of insert() function should be int collection[2][2] or int collection[][2], both are equivalent to int (*collection)[2].
Putting these altogether, you can do:
#include <stdio.h>
#include <string.h>
#define ROW 2
#define COL 2
void insert(int data[ROW], int collection[ROW][COL]) {
//for demonstration purpose, copying elements of data array
//to all elements (1D array) of collection array.
for (int i = 0; i < ROW; ++i) {
memcpy(collection[i], data, COL * sizeof(int));
}
}
int main(void) {
int data[COL] = {1, 3};
int collection[ROW][COL];
insert(data, collection);
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 2; ++j) {
printf("collection[%d][%d] : %d ", i, j, collection[i][j]);
}
printf("\n");
}
return 0;
}
Output:
# ./a.out
collection[0][0] : 1 collection[0][1] : 3
collection[1][0] : 1 collection[1][1] : 3
basically I have 2d array in a struct that I access through a pointer and i can't figure out how to access matrix[i][j] in my if statement
struct Matrix{
unsigned int matrix_size;
int matrix [MAX_MATRIX][MAX_MATRIX];
};
short is_matrix_ok(const struct Matrix*n){
for(int i=0;i<n-matrix_size;i++){
for(int j=0;j<n->matrix_size;j++){
if(n->(matrix+i)[j] ?????)
}
}
Thanks for your answer
Use n->matrix[i][j].
matrix is a member of the structure. matrix+i is not, so you cannot use n->(matrix+i). You must first get the member of the structure, n->matrix, and then you can apply operations to that, like n->matrix[i], which is equivalent to (n->matrix)[i], and then you can apply the next subscript, n->matrix[i][j].
If you want to access it using pointers rather than subscripts, then it would be n->matrix + i to calculate a pointer to subarray i. Then *(n->matrix + i) is that subarray. As an array, it is automatically converted to a pointer to its first element, so *(n->matrix + i) + j calculates a pointer to element j of subarray i. Finally, *(*(n->matrix + i) + j) is element j of subarray i.
Never use that pointer expression in normal code without good reason. Use the easier-to-read n->matrix[i][j].
Try the code below:
#include <stdio.h>
#define ROWS 3
#define COLS 2
struct Matrix{
int matrix[ROWS][COLS];
};
short read_matrix(struct Matrix *M){
int tmp = -100;
for(int i=0;i<ROWS;i++){
for(int j=0;j<COLS;j++){
scanf("%d\n", &tmp);
M->matrix[i][j] = tmp;
//printf("tmp is %d\n", tmp);
}
}
return(0);
}
short is_matrix_ok(const struct Matrix *M){
for(int i=0;i<ROWS;i++){
for(int j=0;j<COLS;j++){
printf("n[%d][%d] = %d\n",i,j,M->matrix[i][j]);
}
}
return(0);
}
int main(){
struct Matrix Mat;
read_matrix(&Mat);
is_matrix_ok(&Mat);
return(0);
}
If you input 1 to 6, output is as follows:
n[0][0] = 1
n[0][1] = 2
n[1][0] = 3
n[1][1] = 4
n[2][0] = 5
n[2][1] = 6
Trying to work on leetcode #497 in C on my vscode. When writing main(), I am not sure how to deal with int** that leetcode provides. Is it possible to pass a 2D array using int**?
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int rectsSize;
int * rectsColSize;
int** rects;
} Solution;
int points[100];
Solution* solutionCreate(int** rects, int rectsSize, int* rectsColSize) {
Solution* sol = malloc(sizeof(Solution));
sol->rects = rects;
sol->rectsSize = rectsSize;
sol->rectsColSize = rectsColSize;
//some codes
}
return sol;
}
int* solutionPick(Solution* obj, int* retSize) {
//some codes
return ret;
}
void solutionFree(Solution* obj) {
free(obj);
}
int main(void)
{
int rects[2][4] = {{1, 1, 5, 5}, {6, 6, 9, 9}};
int rectsSize = 2;
int rectsColSize = 4;
int retSize;
Solution* obj = solutionCreate(rects, rectsSize, &rectsColSize);
int* param_1 = malloc(sizeof(int));
param_1 = solutionPick(obj, &retSize);
solutionFree(obj);
return 0;
}
While in general there are many different ways to handle 2D array, the simple answer is no. There is a lot of info about 2d arrays in C: 1, 2, 3, etc. In principle, when dealing with 2d arrays, every dimension except first to the left needs to be specified exactly. In your case, every rectangle is defined by 4 integers, so instead int** rects consider int*[4] rects. This makes rectsColSize useless, because now each column has constant size of 4 ints.
Just for completness: what you are trying to do is second approach to arrays, where each column has independent size, and (usually) additional malloc call. While this approach is also valid and requires int** type, it is not needed for your task. Nice description of the difference here.
Edit
Here is how to loop through 2d arrays:
#define col 4
void print_2d(int (*a)[col], int aSize){
for(size_t i = 0; i < aSize; i++){
for(size_t j = 0; j < col; j++){
printf("%d ", a[i][j]);
}
printf("\n");
}
}
and here for int**:
void print_pp(int** a, int aSize, int* aiSize){
for(size_t i = 0; i < aSize; i++){
for(size_t j = 0; j < aiSize[i]; j++){
printf("%d ", a[i][j]);
}
printf("\n");
}
}
It seems that you want to convert int*[4] to int**, or more precisely, int*[4] arr2d with it's size int arr2dSize to structure Solution. In that case, here is wrapper to solutionCreate.
Solution* solutionCreateWrap(int (*arr2d)[4], int arr2dSize) {
int* rectsColSize = malloc(arr2dSize * sizeof(int));
int** rects = malloc(arr2dSize * sizeof(int*));
size_t arr2dMem = arr2dSize * 4 * sizeof(int);
rects[0] = malloc(arr2dMem);
memcpy(rects[0], arr2d, arr2dMem);
rectsColSize[0] = 4;
for(size_t i = 1; i < arr2dSize; i++){
rects[i] = rects[0] + i*4;
rectsColSize[i] = 4;
}
sol->rects = rects;
sol->rectsSize = rectsSize;
sol->rectsColSize = rectsColSize;
//some codes
}
return solutionCreate(rects, arr2dSize, rectsColSize);
}
Now for int rects[2][4] = {{1, 1, 5, 5}, {6, 6, 9, 9}}; call solutionCreateWrap(rects, 2) will return initialised structure Solution. It looks gruesome, and it's details are even worse, so if it just works, you may skip the explanation. Understanding low level C details isn't neccesarily to write in it, and this (or any other) explanation cannot possibly cover this matter, so don't be discouraged, if you won't get it all.
arr2d is contiguous block of memory of arr2dSize*4 integers. When multiplied by sizeof(int) we get size in bytes - arr2dMem in my code. Declaration int (*arr2d)[4] means, that arr2d is of type int*[4]. Knowing this we can cast it to int* like so: int* arr = (int*)arr2d and expression arr2d[i][j] is translated as arr[i*4+j].
The translation to rects is as follows; int** is array of pointers, so every rect[i] has to be pointer to i-th row of arr2d. Knowing this, everything else is pointer arithmetic. rects[0] = malloc(arr2dMem); and memcpy(rects[0], arr2d, arr2dMem); copies whole arr2d to rect[0], then every next rects[i] = rects[0] + i*4; is shifted 4 integers forward. Because rect is of type int**, the expression rects[i][j] translates to *(rects[i]+j), and replacing rects[i] by rects[0] + i*4, we get *((rects[0] + 4*i)+j), that is rects[0][4*i+j]. Note striking similarity between last expression, and arr[i*4+j]. rectsColSize is somewhat superfluous in this case, but it is essential in general int** array, when every subarray could have different sizes. After wrap function is done, rects is exact copy of arr2d, but with type appropriate for your Solution structure, so we can call solutionCreate().
I'm a novice in C and I need a structure to pass constant two-dimensional arrays to function as one parameter. I want to make this
const int a_size_x = 20;
const int a_size_y = 30;
const int a_output_array[size_x][size_y] = {{..., ...}, ..., {..., ...}};
const int b_size_x = 20;
const int b_size_y = 30;
const int b_output_array[size_x][size_y] = {{..., ...}, ..., {..., ...}};
void function(const int array[], int arr_size_x, int arr_size_y){
for (int i = 0; i < arr_size_x; i++)
{
for (int j = 0; j < arr_size_y; j++)
{
printf("%i ", array[i][j];
}
printf("\n");
}
function(a_output_array, a_size_x, a_size_y);
function(b_output_array, b_size_x, b_size_y);
easier to be able to call function(a) like this:
const struct OUTPUT
{
const int size_x;
const int size_y;
const int array[size_x][size_y];
};
struct OUTPUT a = {.size_x = 20, .size_y = 30, .array = {{...}, ..., {...}};
....
struct OUTPUT z = {.size_x = 30, .size_y = 20, .array = {{...}, ..., {...}};
function(const struct OUTPUT out){
for (int i = 0; i < out.size_x; i++)
{
for (int j = 0; j < out.size_y; j++)
{
printf("%i ", out.array[i][j];
}
printf("\n");
}
function(a);
function(b);
but of course compiler says that size_x and size_y is undeclared in struct declaration.
I've read about flexible array members, but there's dynamic memory allocation needed, and in AVR Harvard architecture malloc can't work in program memory, where i put all this data.
Is there some way to do it in C? May be, in C++?
UPDATE Answer that worked for me - create a one-dimensional array of lenght 2 + width*height where first two members are true width and height and use a pointer to work with this. Here's an example function to print out this array:
char arr [11] =
{
3 // width
3 // height
1, 2, 3,
4, 5, 6,
7, 8, 9
}
void print_array(char *ptr)
{
char width = *ptr++;
char height= *ptr++;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
print("%c\t", *ptr++);
}
print("\n");
}
}
print_array(arr);
For most compilers, 2D arrays can be refered to as 1D as such:
matrix[3][3]=[1,2,3
4,5,6
7,8,9]
Index in 1D is calculated by row size*row number. For example: matrix[5]=6.
This means you can pass only 1 parameter, the row length, and by calculating the length of the whole vector you can deduce the 2nd parameter (number of rows).
You can add the row length parameter to the end of your array, and by so passing the array only, if that helps.
When declaring an array with an initializer, the bounds of the array must be constants. A variable with a const qualifier does not qualify as a constant. You can however use a macro which does a text substitution:
#define A_SIZE_X 2
#define A_SIZE_Y 3
const int a_output_array[A_SIZE_X][A_SIZE_Y] = {{3,4,5},{6,7,8}};
#define B_SIZE_X 2
#define B_SIZE_Y 3
const int b_output_array[B_SIZE_X][B_SIZE_Y] = {{1,2,3},{4,5,6}};
When passing a 2D array to a function, the definition must say that it expects a 2D array. Your is expecting const int array[] which is a 1D array.
You can have a function accept arrays with different bounds if the bounds are specified first in the definition:
void function(int arr_size_x, int arr_size_y, const int array[arr_size_x][arr_size_y]) {
You can then call it like this:
function(A_SIZE_X, A_SIZE_Y, a_output_array);
function(B_SIZE_X, B_SIZE_Y, b_output_array);
Side note first, the first snippet has a wrong signature and your compiler should warn you:
void function(const int array[], int arr_size_x, int arr_size_y){
here, array is a pointer to int (in a function signature, an array automatically gets adjusted to a pointer), but for passing a 2d array, you would need a pointer to array of int. Did you test that snippet? I assume it doesn't do what you want.
With C99 and above (assuming the compiler supports VLA, variable length arrays), something like this would be correct:
void function( int arr_size_x, int arr_size_y, const int (*array)[arr_size_y]){
As for your idea with a struct, you could only do it when you keep the second dimension fixed. A C array is contiguous in memory, so to do the indexing correctly, the compiler must know all dimensions except for the first one at compile time. VLAs are an exception to that rule, but you can't declare a VLA statically.
What you can do however is using a flat array and do the 2d indexing yourself, like in this tiny example:
struct outputdata
{
size_t rows;
size_t cols;
int *data;
};
const int a_data[] = {1, 2, 3, 4, 5, 6};
const struct outputdata a = {
.rows = 2,
.cols = 3,
.data = a_data
};
// [...]
void function(const struct outputdata x)
{
for (size_t r = 0; r < x.rows; ++r)
{
for (size_t c = 0; c < x.cols; ++c)
{
printf("%d ", x.data[r*x.cols + c]);
}
}
}