Reference to two-dimensional column of an array in C?

Is there an easy way to refer to a column in a two-dimensional array as a separate array from 1-D in plain old C (not C ++ or C #)? This is easy to do for a number. Suppose I have 2 functions:

double doSomethingWithARow( double theRow[3] ); double doSomethingWithACol( double theCol[100] ); 

Then I could 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 so that it can easily access the column.

 for( int j=0; j < 3; j++ ) { result = doSomethingWithACol( ??????????? ); } 

The only thing I have come up with so far is matrix transformation to replace rows with columns. But this code should be as efficient as possible in terms of memory and speed. With all the confusing ways of referencing C pointers, it seems like there should be a way to do this.

+4
source share
5 answers

A good type of types for this without specifying dimensions as 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; } 

For this reason, it is completely wrong to pass double **:

 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 switched to double **, then access to it as an array will lead to breakage, segfault or undefined.

+3
source

Well, you need to pass the row size and the number of rows:

  double doSomethingWithACol(double *matrix, size_t colID, size_t rowSize, size_t nRows); 

Now you can use the fact that the 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 will need to pass a pointer to the first element of the column that you want to process, instead of a pointer to the first row.


Code example: This code summarizes 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; } 
+5
source

Since the "columns" as you call them are stored inconsistently in memory, there is no real way to directly remove this.

However, you can create an array of pointers and store references to the indices of another array in this. You will need to iterate over all the elements in your array, so this is probably not a better solution than any other. Depending on how often you need to access the array by column, it may be useful.

0
source

You cannot do this because arrays in C are stored so that the elements of each row are stored together. This means that the array string is a contiguous block of memory, and as far as C is concerned, it can also be an independent array. It does not work the same way with columns, because the elements of the column are not continuous in memory; rather, they are spaced at intervals of N bytes, where each line has a length of N bytes. This means that you can effectively access various elements of a column of a 2D array using pointer arithmetic, but there is no way to actually make a column in the array itself, except by copying the elements into a new array.

0
source

No no. It cannot be, since in C the array is a sequential part of the memory, and it is trivial that rows and columns cannot be sequential at the same time.

It’s easy to move from one cell 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); 
0
source

All Articles