Qbik
Qbik

Reputation: 6147

How to get column of a multidimensional array in C/C++?

int matrix[9][9],*p;
p=matrix[0]; 

this works and gives first row of matrix, but how to get first column of matrix I've tried p=matrix[][0]; ? Also I don't understand why below code gets compiler error ?

int matrix[9][9],p[9];  // it looks really ugly, byt why it doesn't work ?
p=matrix[0];            // compiler gives "invalid array assigment"

is it because multidimensional arrays are arrays of arrays - and we should interpret matrix[i][j] as j-th element of i-th nested array ?

Upvotes: 5

Views: 52810

Answers (10)

Synck
Synck

Reputation: 3548

C++23 solution using drop & stride views, to create a view on the column elements.

#include <ranges>
#include <print>
#include <vector>

int main()
{
    const auto nrColumns = 3;
    const auto nrRows = 3;
    const int matrix[nrRows][nrColumns] = { 1, 2, 3, 11, 22, 33, 111, 222, 333 };
    const auto values = std::span(matrix[0], nrRows * nrColumns);

    const auto columnIndex = 1;
    const auto columnView = values | std::views::drop(columnIndex) | std::views::stride(nrColumns);

    for(const auto& value : columnView)
    {
        std::print("{0}, ", value);
    }
}

Returns 2, 22, 222,

Try it yourself: https://godbolt.org/z/bG5Md4zs7

Upvotes: 1

TnT
TnT

Reputation: 11

Here's a program which builds a 10x10 array and prints the second column:

#include <iostream>

using namespace std;

int main()
{
   int aa[10][10];

   for(int i = 0; i<10; i++)
       for(int j = 0; j<10; j++)
           aa[i][j] = i*10+j;
   
   int col = 2;

   // pointer to a length-10 1d array
   int (*p)[10] = (int (*)[10])&(aa[0][col]);

   for(int i =0; i<10; i++)
      cout << *(p[i]) << endl;

   return 0;
}

The difference from aa[row][2] is using a pointer to a length-10 1d int array int (*p)[10], For more context about int (*p)[10], see this answer

p saves the address of 1d array {2, 3, 4, 5, 6, 7, 8, 9, 10, 11} . And p+1 saves the address of 1d array {12, 13, 14, 15, 16, 17, 18, 19, 20, 21}. *(p[1]) or *(*(p+1)) access the first value of 1d array.

Upvotes: 1

Aarat
Aarat

Reputation: 31

I don't know if this is a efficient solution but by doing this way I'm able to get the column,

int arr[9][2] = { {2,  57}, {3,  66}, {4,  73}, {5,  76}, {6,  79}, {7,  81}, {8,  90}, {9,  96}, {10, 100}};

int c[18];
int co = 0;
for (auto & i : arr) {
    for (int j : i) {
        c[co++] = j;
    }
}

for (int i = 0; i < co; ++i) {
    if (i % 2 != 0)
        std::cout << c[i] << " ";
}

Upvotes: 0

Georgi
Georgi

Reputation: 1

For static declared arrays you can access them like continuous 1D array, p = matrix[0] will give you the 1st column of 1st row. Then the 1D array can be accessed like p[i], *(p+i), or p[current_raw * raw_size + current_column).

The things are getting tricky if a 2D array is represented with **p as it will be interpreted as an array of pointers to 1D arrays.

Upvotes: 0

user2137101
user2137101

Reputation:

You can get the first column using a loop like

for(int i = 0; i < 9; i++)
{
    printf("Element %d: %d", i, matrix[i][0]);
}

I think the assignment doesn't work properly because you're trying to assign something's that's not an address to a pointer.

(Sorry this is c code)

Upvotes: 8

meyumer
meyumer

Reputation: 5064

In C/C++, multidimensional arrays are actually stored as one dimensional arrays (in the memory). Your 2D matrix is stored as a one dimensional array with row-first ordering. That is why getting a column out of it is not easy, and not provided by default. There is no contiguous array in the memory that you can get a pointer to which represents a column of a multidimensional array. See below:

When you do p=matrix[0], you are just getting the pointer to the first element matrix[0][0], and that makes you think that you got the pointer to first row. Actually, it is a pointer to the entire contiguous array that holds matrix, as follows:

matrix[0][0]
matrix[0][1]
matrix[0][2]
.
.
matrix[1][0]
matrix[1][1]
matrix[1][2]
.
.
matrix[8][0]
matrix[8][1]
matrix[8][2]
.
.
matrix[8][8]

As seen above, the elements of any given column are separated by other elements in the corresponding rows.

So, as a side note, with pointer p, you can walk through the entire 81 elements of your matrix if you wanted to.

Upvotes: 16

AxelOmega
AxelOmega

Reputation: 972

There is no difference between specifying matrix[81] or matrix[9][9]

matrix[r][c] simply means the same as matrix[9*r+c]

There are other containers better suited fort multidimensional arrays like boost::multi_array

http://www.boost.org/doc/libs/1_53_0/libs/multi_array/doc/index.html

Think of the bare array just like allocating a contiguous piece of memory. You, the programmer then has to handle this piece of memory yourself. The bare name of the array, e.g. matrix is a pointer to the first element of this allocated piece of memory. Then *(matrix+1) is the same as matrix[0][1] or matrix[1].

Upvotes: 4

Thomas Matthews
Thomas Matthews

Reputation: 57678

If you want your matrix to contiguous locations, declare it as a one dimensional array and perform the row and column calculations yourself:

int contiguous_matrix[81];

int& location(int row, int column)
{
  return contiguous_matrix[row * 9 + column];
}

You can also iterate over each column of a row:

typedef void (*Function_Pointer)(int&);

void Column_Iteration(Function_Pointer p_func, int row)
{
  row = row * MAXIMUM_COLUMNS;
  for (unsigned int column = 0; column < 9; ++column)
  {
    p_func(contiguous_matrix[row + column]);
  }
}

Upvotes: 0

Neil
Neil

Reputation: 55392

matrix itself is the nearest thing you can get to a column of the array, inasmuch as (matrix + 1)[0][0] is the same as matrix[1][0].

Upvotes: 1

zzk
zzk

Reputation: 1387

p is an array of int, matrix[0] is a pointer..

Upvotes: 2

Related Questions