Working with a Matrix/2D Array in Your C and C++ programs.

preview_player
Показать описание
---

Working with a Matrix/2D Array in Your C and C++ programs // This video talks about how to declare, allocate, and manage multidimensional arrays, like matrices. Declaring a matrix and passing it to a function has some potential pitfalls. This video will help you be aware of them.

Related Videos:

***

Welcome! I post videos that help you learn to program and become a more confident software developer. I cover beginner-to-advanced systems topics ranging from network programming, threads, processes, operating systems, embedded systems and others. My goal is to help you get under-the-hood and better understand how computers work and how you can use them to become stronger students and more capable professional developers.

About me: I'm a computer scientist, electrical engineer, researcher, and teacher. I specialize in embedded systems, mobile computing, sensor networks, and the Internet of Things. I teach systems and networking courses at Clemson University, where I also lead the PERSIST research lab.

More about me and what I do:

To Support the Channel:
+ like, subscribe, spread the word

Рекомендации по теме
Комментарии
Автор

Another solution I like and use quite often when I don't know the dimensions of the matrix in advance is to actually just store matrices in one dimension, like int *matrix = new int[rows * cols], then index it with matrix[row * cols + col]. This way the memory is assured to be contiguous and it's easy and efficient to just memcpy the whole array if you need to duplicate it.

fmdj
Автор

Please correct me if am wrong, is there a bug in the for loop from the main scope, specifically accessing memory which is not yours? MATRIX_ROWS same for both loops

mrcjproject
Автор

In "main" and "print_matrix" functions of C program (before refactoring) you have serious bug: you're writing and reading (respectivly) 4 bytes (1 position) behind 2 dimensional array. Second for loop should have condition: col < MATRIX_COLS instead of col < MATRIX_ROWS.

wiktorwektor
Автор

One thing to keep in mind is that in C/C++, "const" doesn't actually mean compile time constant and really just means immutable. (C++ does have constexpr for that, but C, at least at the moment, does not) If you use a "const int" as an array specifier for a variable, it will be a VLA, regardless of if the value can be deduced at compile time. This is different from C++ (which doesn't have VLAs).

Currently in C the only way to have "MATRIX_ROWS"/"MATRIX_COLS" be a compile time constant is to either use macros or enums.

Also, for C23, the committee passed a proposal that makes it such that only stack allocated VLAs with automatic storage duration will be optional with all other types of VMTs/VLAs being mandatory. This means VLAs as function parameters and pointers to VLAs will be mandatory. (this also means "sizeof(int[rows][colls])" will be mandatory)

oreo
Автор

I was taught arrays in slightly different way, and that used to confuse me. An array (the subscript syntax) is a syntactic sugar over pointers. So when one is doing int array[5]; and printing it with printf("%d", array[3]); for example, then they are effectively doing *(array + 3) and printing that value. The name given to an array is always a pointer to the first location, that is, the zeroth cell. So array[x] is the same as *(array + x) and it is pointer math.

Having said that, at 16:57, instead of dynamically allocating the memory, you can still create the matrix as int and let the compiler actually reserve the memory for you by allocating the values in stack, and when you need to pass to the function, pass a pointer instead. Then you can pass the matrix address to the function where the signature becomes this:

void printMatrix(int *matrix, int rows, int cols);

And when we need to do matrix[y][x], we access it as *(matrix + x + y * cols). However, one thing that bothered me is I wasn't able to access it as matrix[y][x], even if I pass matrix to the function as a doubly pointer. When tried using IDEOne, it crashed with a Segmentation Fault at runtime. Any idea what might be going on?

SriHarshaChilakapati
Автор

Good lesson. The next video could be about using one allocation for all ints at once and then just pointing to them. It not only saves many allocations, but it makes sure that the allocated memory is sequential, which might make a performance difference.

ronnysherer
Автор

I prefer doing 1D way - accessing [x + y * columns]. With that allocation is needed only once. It can also work in more dimensions [x + y * columns + z * columns * rows].

AgnisNeZvers
Автор

Many commenters have suggested flattening the matrix into a 1D array, and indexing it with matrix[row*cols + col], as a flattened matrix is nicer to the cache, and easier to allocate and deallocate. I would like to point out that you can have a flattened matrix and yet keep an array of pointers to rows that lets you have the more convenient syntax matrix[row][col]. This is done as follows:

int **matrix = calloc(MATRIX_ROWS, sizeof *matrix);
*matrix = calloc(MATRIX_ROWS * MATRIX_COLS, sizeof **matrix);
for (int row = 1; row < MATRIX_ROWS; row++)
matrix[row] = *matrix + row * MATRIX_COLS;

edgarbonet
Автор

I kind of already knew all this, but only kind of, so this was a great refresher. Like others here I would also like to see how you would do a version where the entire matrix is allocated all at once as an array of int's, and then you manually access them given a row and col. I did this recently in one of my projects.

zrodger
Автор

Hey Jacob, excellent video as always, thank you! Definitely didn't know about those peculiar ways of passing 2D arrays in C functions. You will often encounter another kind of way around this issue, and that is casting everything to a 1D array (as memory is just one string of bytes), and then access it by something like; { array[ row * MATRIX_COLS + col ] = ( row << 16 ) | col; }

LogicEu
Автор

3:53 Who else was waiting for him to notice that MATRIX_ROWS in the inner loop should be MATRIX_COLS?

ianmathwiz
Автор

Huh, this video sure was timely. Thanks Jacob.

burlapjack
Автор

I was literally just looking at this topic yesterday!

nickbrian
Автор

Great as always. Happy that I can follow this time.

yangliu
Автор

Jacob: "I don't wanna confuse anyone"
.
.
.
Also Jacob: uses << with |

AdisDurakovic
Автор

I think you missed the method of allocating the whole matrix as a single continuous array and then using pointer math to get to the element.

tomatus
Автор

Thank you for this video, very informative.

nemis
Автор

I'll just say, the C++ version is very old school. Prefer std::array over C style array, or use std::vector. this is why some of us love C++, otherwise one may as well just use C if you are going to new and delete everything.

afborro
Автор

I am confused about why you didn't get an access violation/out of bounds error with both nested for loops due to using MATRIX_ROWS with col

TarousDT
Автор

@18:30 (switching to alloc'd buffers) The use of "**" probably scares beginners.
The alternate equivalent is, of course, int *matrix[] = calloc....
Even though they are the same, the square bracket version provides a clue (especially in the parameter list of the print function) that the var points to a contiguous array...

void main( int argc, char *argv[] ) {

rustycherkas