How can I use int** to pass a 2D array in C - c

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().

Related

How many pointers are in an array of pointers

I dynamically allocated memory for 3D array of pointers. My question is how many pointers do I have? I mean, do I have X·Y number of pointers pointing to an array of double or X·Y·Z pointers pointing to a double element or is there another variant?
double*** arr;
arr = (double***)calloc(X, sizeof(double));
for (int i = 0; i < X; ++i) {
*(arr + i) = (double**)calloc(Y, sizeof(double));
for (int k = 0; k < Y; ++k) {
*(*(arr+i) + k) = (double*)calloc(Z, sizeof(double));
}
}
The code you apparently intended to write would start:
double ***arr = calloc(X, sizeof *arr);
Notes:
Here we define one pointer, arr, and set it to point to memory provided by calloc.
Using sizeof (double) with this is wrong; arr is going to point to things of type double **, so we want the size of that. The sizeof operator accepts either types in parentheses or objects. So we can write sizeof *arr to mean “the size of a thing that arr will point to”. This always gets the right size for whatever arr points to; we never have to figure out the type.
There is no need to use calloc if we are going to assign values to all of the elements. We can use just double ***arr = malloc(X * sizeof *arr);.
In C, there is no need to cast the return value of calloc or malloc. Its type is void *, and the compiler will automatically convert that to whatever pointer type we assign it to. If the compiler complains, you are probably using a C++ compiler, not a C compiler, and the rules are different.
You should check the return value from calloc or malloc in case not enough memory was available. For brevity, I omit showing the code for that.
Then the code would continue:
for (ptrdiff_t i = 0; i < X; ++i)
{
arr[i] = calloc(Y, sizeof *arr[i]);
…
}
Notes:
Here we assign values to the X pointers that arr points to.
ptrdiff_t is defined in stddef.h. You should generally use it for array indices, unless there is a reason to use another type.
arr[i] is equivalent to *(arr + i) but is generally easier for humans to read and think about.
As before sizeof *arr[i] automatically gives us the right size for the pointer we are setting, arr[i].
Finally, the … in there is:
for (ptrdiff_t k = 0; k < Y; ++k)
arr[i][k] = calloc(Z, sizeof *arr[i][k]);
Notes:
Here we assign values to the Y pointers that arr[i] points to, and this loop is inside the loop on i that executes X times, so this code assigns XY pointers in total.
So the answer to your question is we have 1 + X + XY pointers.
Nobody producing good commercial code uses this. Using pointers-to-pointers-to-pointers is bad for the hardware (meaning inefficient in performance) because the processor generally cannot predict where a pointer points to until it fetches it. Accessing some member of your array, arr[i][j][k], requires loading three pointers from memory.
In most C implementations, you can simply allocate a three-dimensional array:
double (*arr)[Y][Z] = calloc(X, sizeof *arr);
With this, when you access arr[i][j][k], the compiler will calculate the address (as, in effect, arr + (i*Y + j)*Z + k). Although that involves several multiplications and additions, they are fairly simple for modern processors and are likely as fast or faster than fetching pointers from memory and they leave the processor’s load-store unit free to fetch the actual array data. Also, when you are using the same i and/or j repeatedly, the compiler likely generates code that keeps i*Y and/or (i*Y + j)*Z around for multiple uses without recalculating them.
Well, short answer is: it is not known.
As a classic example, keep in mind the main() prototype
int main( int argc, char** argv);
argc keeps the number of pointers. Without it we do not know how many they are. The system builds the array argv, gently updates argc with the value and then launches the program.
Back to your array
double*** arr;
All you know is that
arr is a pointer.
*arr is double**, also a pointer
**arr is double*, also a pointer
***arr is a double.
What you will get in code depends on how you build this. A common way if you need an array of arrays and things like that is to mimic the system and use a few unsigned and wrap them all with the pointers into a struct like
typedef struct
{
int n_planes;
int n_rows;
int n_columns;
double*** array;
} Cube;
A CSV file for example is char ** **, a sheet workbook is char ** ** ** and it is a bit scary, but works. For each ** a counter is needed, as said above about main()
A C example
The code below uses arr, declared as double***, to
store a pointer to a pointer to a pointer to a double
prints the value using the 3 pointers
then uses arr again to build a cube of X*Y*Z doubles, using a bit of math to set values to 9XY9.Z9
the program uses 2, 3 and 4 for a total of 24 values
lists the full array
list the first and the very last element, arr[0][0][0] and arr[X-1][Y-1][Z-1]
frees the whole thing in reverse order
The code
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int n_planes;
int n_rows;
int n_columns;
double*** array;
} Cube;
int print_array(double***, int, int, int);
int main(void)
{
double sample = 20.21;
double* pDouble = &sample;
double** ppDouble = &pDouble;
double*** arr = &ppDouble;
printf("***arr is %.2ff\n", ***arr);
printf("original double is %.2ff\n", sample);
printf("*pDouble is %.2ff\n", *pDouble);
printf("**ppDouble is %.2ff\n", **ppDouble);
// but we can build a cube of XxYxZ doubles for arr
int X = 2;
int Y = 3;
int Z = 4; // 24 elements
arr = (double***)malloc(X * sizeof(double**));
// now each arr[i] must point to an array of double**
for (int i = 0; i < X; i += 1)
{
arr[i] = (double**)malloc(Y * sizeof(double*));
for (int j = 0; j < Y; j += 1)
{
arr[i][j] = (double*)malloc(Z * sizeof(double));
for (int k = 0; k < Z; k += 1)
{
arr[i][j][k] = (100. * i) + (10. * j) + (.1 * k) + 9009.09;
}
}
}
print_array(arr, X, Y, Z);
printf("\n\
Test: first element is arr[%d][%d[%d] = %6.2f (9XY9.Z9)\n\
last element is arr[%d][%d[%d] = %6.2f (9XY9.Z9)\n",
0, 0, 0, arr[0][0][0],
(X-1), (Y-1), (Z-1), arr[X-1][Y-1][Z-1]
);
// now to free this monster
for (int x = 0; x < X; x += 1)
{
for (int y = 0; y < Y; y += 1)
{
free(arr[x][y]); // the Z rows
}
free(arr[x]); // the plane Y
}
free(arr); // the initial pointer;
return 0;
}; // main()
int print_array(double*** block, int I, int J, int K)
{
for (int a = 0; a < I; a += 1)
{
printf("\nPlane %d\n\n", a);
for (int b = 0; b < J; b += 1)
{
for (int c = 0; c < K; c += 1)
{
printf("%6.2f ", block[a][b][c]);
}
printf("\n");
}
}
return 0;
}; // print_array()
The output
***arr is 20.21f
original double is 20.21f
*pDouble is 20.21f
**ppDouble is 20.21f
Plane 0
9009.09 9009.19 9009.29 9009.39
9019.09 9019.19 9019.29 9019.39
9029.09 9029.19 9029.29 9029.39
Plane 1
9109.09 9109.19 9109.29 9109.39
9119.09 9119.19 9119.29 9119.39
9129.09 9129.19 9129.29 9129.39
Test: first element is arr[0][0[0] = 9009.09 (9XY9.Z9)
last element is arr[1][2[3] = 9129.39 (9XY9.Z9)

Pass a constant two-dimensional array to function as a structure in C

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]);
}
}
}

Getting a subroutine to return three seperate arrays of random numbers in C

I currently have code for a subroutine to return a pointer to an array. This array is a list of random numbers for a one dimensional monte-carlo integral. I am now trying to do a multi dimensional equivalent which requires 3 arrays of random numbers and instead of having a separate subroutine for each I'm trying to make one which returns a 3 by N + 1 array. Could somebody please help me with the coding for this. A mate mentioned I would need a double pointer but most web sources have been unhelpful thus far. Here is my single array code:
double* rdm_Y(void)
{
double* Random_number_list_Y = calloc(N + 1, sizeof(double));
int i;
sleep(1);
srand(time(NULL));
for (i = 1; i <= N; i++) {
Random_number_list_Y[i] = (float) rand() / (float) RAND_MAX;
}
return Random_number_list_Y;
}
Many Thanks!
Jack Medley
The general pattern for dynamically allocating a 2D array of type T (where T can be int, double, etc.) is
#include <stdlib.h>
T **alloc(size_t rows, size_t columns)
{
T **arr = malloc(sizeof *arr, rows); // type of *arr is T *
if (arr)
{
size_t i;
for (i = 0; i < rows; i++)
{
arr[i] = malloc(sizeof *arr[i], columns); // type of *arr[i] is T
if (arr[i])
{
size_t j;
for (j = 0; j < columns; j++)
{
arr[i][j] = initial_value_for_this_element;
}
}
}
}
return arr;
}
Try:
struct res{
double *arr1, *arr2, *arr3;
};
main(){
struct res r;
r.arr1 = rdm_Y();
r.arr2 = rdm_Y();
r.arr3 = rdm_Y();
// in r you have 3 pointers to 3 separate arrays
}
or something like this
The three methods I can think of are:
A *double to a 1D array of size 3xN (you can just pretend it's three arrays)
A **double to an array of three *doubles, each one pointing to an array of N
A struct containing three *doubles, each one pointing to an array of N
If you don't like pretending for method 1 you can declare two more *doubles and set them to the return value + N and + 2N respectively. Also don't forget to free() you should have 1, 4, and 3 free()s to do for each of the methods respectively.

Define a matrix and pass it to a function in C

I want to create a program in which I can pass a matrix to a function using pointers.
I initialized and scanned 2 matrices in the void main() and then I tried to pass them to a void add function. I think I am going wrong in the syntax of declaration and calling of the function. I assigned a pointer to the base address of my matrix. (for eg: int *x=a[0][0], *y=b[0][0]). What is the right declaration? How can I specify the dimensions?
Given a 2D array of
T a[N][M];
a pointer to that array would look like
T (*ap)[M];
so your add function prototype should look like
void add(int (*a)[COLS], int (*b)[COLS]) {...}
and be called as
int main(void)
{
int a[ROWS][COLS];
int b[ROWS][COLS];
...
add(a, b);
However, this code highlights several problems. First is that your add function is relying on information not passed via the parameter list, but via a global variable or symbolic constant; namely, the number of rows (the number of columns is explicitly provided in the type of the parameters). This tightly couples the add function to this specific program, and makes it hard to reuse elsewhere. For your purposes this may not be a problem, but in general you only want your functions to communicate with their callers through the parameter list and return values.
The second problem is that as written, your function will only work for matrices of ROWS rows and COLS columns; if you want to add matrices of different sizes within the same program, this approach will not work. Ideally you want an add function that can deal with matrices of different sizes, meaning you need to pass the sizes in as separate parameters. It also means we must change the type of the pointer that we pass in.
One possible solution is to treat your matrices as simple pointers to int and manually compute the offsets instead of using subscripts:
void add (int *a, int *b, size_t rows, size_t cols)
{
size_t i;
for (i = 0; i < rows; i++)
{
size_t j;
for (j = 0; j < cols; j++)
{
*(a + cols * i + j) += *(b + cols * i + j);
}
}
}
and call it like so:
int main(void)
{
int a[ROWS][COLS] = {...};
int b[ROWS][COLS] = {...};
int c[ROWS2][COLS2] = {...};
int d[ROWS2][COLS2] = {...};
...
add(a[0], b[0], ROWS, COLS);
add(c[0], d[0], ROWS2, COLS2);
...
}
The types of a[0] and b[0] are "COLS-element arrays of int"; in this context, they'll both be implicitly converted to "pointer to int". Similarly, c[0] and d[0] are also implicitly converted to int *. The offsets in the add() function work because 2D arrays are contiguous.
EDIT I just realized I was responding to caf's example, not the OP, and caf edited his response to show something very similar to my example. C'est la guerre. I'll leave my example as is just to show a slightly different approach. I also think the verbiage about passing information between functions and callers is valuable.
Something like this should do the trick.
#define COLS 3
#define ROWS 2
/* Store sum of matrix a and b in a */
void add(int a[][COLS], int b[][COLS])
{
int i, j;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
a[i][j] += b[i][j];
}
int main()
{
int a[ROWS][COLS] = { { 5, 10, 5} , { 6, 4, 2 } };
int b[ROWS][COLS] = { { 2, 3, 4} , { 10, 11, 12 } };
add(a, b);
return 0;
}
EDIT: Unless you want to specify the dimensions at runtime, in which case you have to use a flat array and do the 2D array arithmetic yourself:
/* Store sum of matrix a and b in a */
void add(int rows, int cols, int a[], int b[])
{
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
a[i * cols + j] += b[i * cols + j];
}
#caf has shown a good code example.
I'd like to point out that:
I assigned a pointer to the base
address of my matrix. (for eg: int
*x=a[0][0],*y=b[0][0]).
You are not assining a pointer to the base of the matrix. What this does is assign to the value pointed by x and y, the base value in a and b respectively.
The right way would be
int (*x)[] = a;
int (*y)[] = b;
or alternatively
int *x = &a[0][0];
int *y = &b[0][0];

Reference a 2-D array column in C?

Is there an easy way to reference a column in a 2-D array as a separate 1-D array in plain old C (not C++ or C#)? It's easy to do this for a row. Asssume I have 2 functions:
double doSomethingWithARow( double theRow[3] );
double doSomethingWithACol( double theCol[100] );
Then, I might use the first one like this:
double matrix[100][3];
double result;
// pass a single row to a function as an array
// this essentially passes the 3-element array at row 48 to the function
for( int i=0; i < 100; i++ )
{
result = doSomethingWithARow( matrix[i] );
}
What I want it a way to access a column easily.
for( int j=0; j < 3; j++ )
{
result = doSomethingWithACol( ??????????? );
}
The only thing I've come up with so far is transforming the matrix to swap the rows with the columns. But this code is supposed to be as efficient as possible in terms of memory and speed. With all of the convoluted ways to reference pointers in C, it seems like there should be a way to do this.
Well, you'd have to pass the size of a row, and the number of rows:
double doSomethingWithACol(double *matrix, size_t colID, size_t rowSize, size_t nRows);
Now you can make use of the fact that matrix[i][j] = matrix + i * rowSize + j;
Alternatively, you can also use the following signature:
double doSomethingWithACol(double *colPtr, size_t rowSize, size_t nRows);
Here, you'll have to pass the pointer to the first element of the column that you want to process, instead of the pointer to the first row.
Example code: This code sums the elements in the second column (compile with gcc -o main -Wall -Wextra -pedantic -std=c99 test.c):
#include <stdio.h>
#include <stdlib.h>
double colSum1(double *matrix, size_t colID, size_t rowSize, size_t nRows)
{
double *c = NULL, *end = matrix + colID + (nRows * rowSize);
double sum = 0;
for (c = matrix + colID; c < end; c += rowSize) {
sum += *c;
}
return sum;
}
double colSum2(double *colPtr, size_t rowSize, size_t nRows)
{
double *end = colPtr + (nRows * rowSize);
double sum = 0;
for (; colPtr < end; colPtr += rowSize) {
sum += *colPtr;
}
return sum;
}
int
main(void)
{
double matrix[4][3] = {
{0, 1, 2},
{3, 4, 5},
{6, 7, 8},
{9, 10, 11}
};
printf("%f\n", colSum1(*matrix, 1, 3, 4));
printf("%f\n", colSum2(&matrix[0][1], 3, 4));
printf("%f\n", colSum2(matrix[0] + 1, 3, 4));
return EXIT_SUCCESS;
}
A nice typesafe way to do this without specifying the dimensions as a separate parameters is as follows:
#define ROWS 100
#define COLUMNS 30
void doSomethingToAllRows(double (*row)[ROWS][COLUMNS], int col, double val)
{
for(size_t i = 0; i < ROWS; ++i)
(*row)[i][col] = val;
}
void doSomethingToAllColumns(double (*col)[ROWS][COLUMNS], int row, double val)
{
for(size_t i = 0; i < COLUMNS; ++i)
(*col)[row][i] = val;
}
int main(int argc, char **argv)
{
double matrix[ROWS][COLUMNS];
/* Modify each column of the 10th row with the value of 3 */
doSomethingToAllColumns(&matrix, 10, 3);
/* Modify each row of the 10th column with the value of 3 */
doSomethingToAllRows(&matrix, 10, 3);
return 0;
}
It is completely wrong to pass a double ** for this reason:
void test()
{
double **a;
int i1 = sizeof(a[0]);//i1 == 4 == sizeof(double*)
double matrix[ROWS][COLUMNS];
int i2 = sizeof(matrix[0]);//i2 == 240 == COLUMNS * sizeof(double)
}
If you passed in a double ** then accessed it like an array you would cause a crash, segfault or undefined behavior.
Since the "columns" as you call them are stored discontiguously in memory, there's no real way to pull this off directly.
You can, however, create an array of pointers, and store references to the indexes of the other array in that one. You'd need to loop through all of the elements in your array, so it's probably not a better solution than any other. Depending on how often you need to access the array by column it might be worthwhile, though.
You can't really do that, because arrays in C are stored such that the elements of each row are stored together. That means a row of an array is a continuous block of memory, and as far as C is concerned it might as well be an independent array itself. It doesn't work the same way with columns because the elements of a column are not continuous in memory; rather they are spaced at intervals of N bytes, where each row is N bytes long. This means that you could efficiently access the various elements of a column of a 2D array by using pointer arithmetic, but there's no way to actually make a column into an array itself other than by copying the elements over into a new array.
No, there isn't. There cannot be, since in C, an array is a consecutive part of memory, and it is trivial that rows and columns cannot be consecutive at the same time.
That being said, it is fairly easy to jump from one cell of a column to the next, if you know the length of the rows. Take the following example:
void processColumn(double *array, int colIdx, int rowLen, int rowCnt) {
for (int i = colIdx; i < rowCnt * rowLen; i += rowLen) {
// do whatever you want
}
}
#define N 5
#define M 10
double array[N*M];
processColumn(array, 3, N, M);

Resources