Just remember, that when you're accessing array elements, all array subscripts are sugar for pointer arithmetics. a[2] is sugar for *(a+2). b[size][2] is sugar for *( *(b+size) + 2 ). Then, of course, it makes sense why `arrParam[2][2]` does not work for pointer-decayed arrays: it's *( *(arrParam + 2) + 2 ), which in this case *( 3 + 2 ). and explains why arrParam[10] is ok: *( arrParam + 10 ) The additional subscript doesn't add a dimension to the pointer. This would make no sense. [x][y] multiplies the x dimension y times. Just like you would if you were drawing a table. You can initialise a multidimensional array like this: `arr[2][2] = { 1,2,3,4 };` and it will be the same as `arr[2][2] = {{ 1,2 }, { 3,4 }}` arr[0][2] == arr[1][0] == *( arr[0] + 2 ) == *( arr[1] ) == *( *arr + 2 )
After many unsuccessful attempts, I finally understood the logic behind arrays in c and a good way of passing a 2d array in a function. Wow, amazing work dude.
This is **not** a proper way to pass a 2d array. The proper one is `void foo(int rows, int cols, int arr[rows][cols])`, next the function will be called with `foo(5, 5, arr)`.
@@tomaszstanislawski457he literally used this same way with the single array. More of a generalised way is to pass each dimension individually alongside the array. But that was not the point of the video. The video explains how we can visually interpret what happens in memory since all entities that we allegedly declare as arrays are nothing but a contiguous collection of values in memory that we can access them linearly through pointer arithmetics. The idea was clear at least in my opinion.
@@wassimhaimoudiTechnically speaking accessing `int[5][5]` as `int[25]` for index 5 or larger is Undefined Behavior due to doing pointer arithmetic outside of the object. Only the first row of type `int[5]` can be accessed this way. IMO, using VLA typed parameters is a cleanest and most readable way of handling 2-d arrays.
The cast to `(int*)` can easily invoke UB since accessing 1-D array is allowed only for indices 0 to 5. The proper declaration of `printSize` would be `void printSize(int (*arrParam)[5])` or `void printSize(int arrParam[][5])`.
what do you think about this way: double a1[] = { 0.5,-1.0,-1.0 }; double a2[] = {-1.0, 1.0, 2.0 }; double a3[] = {-1.0, 2.0, 1.0 }; double *A[3]; A[0] = a1; A[1] = a2; A[2] = a3; if you pass A to a function as a double**, you have no problem at all
0:13 me whenever I learn anything related to coding LMAOOO Thank you for making this video! I didn't understand this concept at all in class and I need to learn it to do homework tonight
This channel is not for beginner level c tutorial. It's more like you learnt the basic c terms and trying to make a project and getting your concepts more clear.
Well, there are tons of tutorials for absolute beginners out there but, what most people need is more intermediate level concepts. Especially when dealing with C. Those are the ones harder to grasp and difficult to explain to students
Hey, CodeVault. I'm having a hard time understanding this topic. In 11:37 you say if I dereference a 2D Array I'll get just the first integer of the matrix, but when I done that in my main() function actually what I get is an error, because it expects an variable of type array, with is true because matrix[0] have an array. I really don't get that part, why *matrix works differentelly in a function parameter and main.
Arrays have a lot of "syntactic sugar" around them. When you define an array: int arr[10][10]; This is actually just 100 integers one after the other in memory and nothing else. But when you pass it as double pointer to a function: fun(int** arr); This assumes you have an array of pointers to arrays of int. And the memory layout for that is completely different. So, when you have a 2D array you have to pass it as a single pointer and dereference it accordingly: void fun(int* arr) { arr[i * 10 + j]; // i-th row, j-th column } When it's in main, the compiler does that automatically for you: int arr[10][10]; arr[i][j]; // this is the same dereference as the one in the function
Thank you for the video! I just have one question, why do you have to convert the two dimensional array to an integer pointer in the main function before passing it to the function, I thought that an array becomes an integer pointer anyway when getting passed to a function?
That's true, you don't have to cast that parameter there. But since I was casting a 2d array to a pointer, the compiler would give me a warning which I didn't want
Sir , an array declared in heap using malloc is global or not, as it retains in memory even after function returns , so can we edit it in any other function without passing as argument instead simply calling inside the fun by the ptr name
Well... it's accessible from anywhere. But you still need a variable in function you want to use it that contains the address to that array. Otherwise you cannot just access it if its pointer is stored in another function. void functiona() { int arr = malloc(sizeof(int) * 5); } void functionb() { arr[0] = 5; // ERROR: Undefined variable arr } int main() { functiona(); functionb(); return 0; } So the memory you allocated in functiona is still there BUT you don't have access to it in functionb because you also need a pointer to it. And that pointer is local to functiona right now
I think you can just do something like... without the cast void printArr(int *arrArg) { printf(" arg[0][2] : %d",(arrArg[0]+2)); } int main(void) { int arr[][5] = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, }; printArr(arr); }
Just remember, that when you're accessing array elements, all array subscripts are sugar for pointer arithmetics.
a[2] is sugar for *(a+2).
b[size][2] is sugar for *( *(b+size) + 2 ).
Then, of course, it makes sense why `arrParam[2][2]` does not work for pointer-decayed arrays:
it's *( *(arrParam + 2) + 2 ), which in this case *( 3 + 2 ).
and explains why arrParam[10] is ok: *( arrParam + 10 )
The additional subscript doesn't add a dimension to the pointer. This would make no sense.
[x][y] multiplies the x dimension y times. Just like you would if you were drawing a table.
You can initialise a multidimensional array like this:
`arr[2][2] = { 1,2,3,4 };`
and it will be the same as
`arr[2][2] = {{ 1,2 }, { 3,4 }}`
arr[0][2] == arr[1][0] == *( arr[0] + 2 ) == *( arr[1] ) == *( *arr + 2 )
That initialization example is a great one to understand this concept. Very nice explanation!
This is a fancy channel of C programming. I love this. Thanks for your effort.
Excellent presentation of dealing with multi arrays outside the calling fucntion.
Wow, I never realized it was like so! I could swear using arrParam[0][0] inside the function would work. Thanks for this!
After many unsuccessful attempts, I finally understood the logic behind arrays in c and a good way of passing a 2d array in a function.
Wow, amazing work dude.
This is **not** a proper way to pass a 2d array. The proper one is `void foo(int rows, int cols, int arr[rows][cols])`, next the function will be called with `foo(5, 5, arr)`.
@@tomaszstanislawski457he literally used this same way with the single array. More of a generalised way is to pass each dimension individually alongside the array. But that was not the point of the video. The video explains how we can visually interpret what happens in memory since all entities that we allegedly declare as arrays are nothing but a contiguous collection of values in memory that we can access them linearly through pointer arithmetics. The idea was clear at least in my opinion.
@@wassimhaimoudiTechnically speaking accessing `int[5][5]` as `int[25]` for index 5 or larger is Undefined Behavior due to doing pointer arithmetic outside of the object. Only the first row of type `int[5]` can be accessed this way. IMO, using VLA typed parameters is a cleanest and most readable way of handling 2-d arrays.
Top explanation. Seen others but yours is concise and good to understand. Thx
Best teacher. My pain and anguish have been extinguished!
Thanks sir, you just saved me from another segmentation fault pain
The cast to `(int*)` can easily invoke UB since accessing 1-D array is allowed only for indices 0 to 5. The proper declaration of `printSize` would be `void printSize(int (*arrParam)[5])` or `void printSize(int arrParam[][5])`.
You are the best always telling the gist.
what do you think about this way:
double a1[] = { 0.5,-1.0,-1.0 };
double a2[] = {-1.0, 1.0, 2.0 };
double a3[] = {-1.0, 2.0, 1.0 };
double *A[3];
A[0] = a1;
A[1] = a2;
A[2] = a3;
if you pass A to a function as a double**, you have no problem at all
I love these low-level videos.
Love your videos 🙌
0:13 me whenever I learn anything related to coding LMAOOO
Thank you for making this video! I didn't understand this concept at all in class and I need to learn it to do homework tonight
This channel is not for beginner level c tutorial. It's more like you learnt the basic c terms and trying to make a project and getting your concepts more clear.
Thst's more like it.
Well, there are tons of tutorials for absolute beginners out there but, what most people need is more intermediate level concepts. Especially when dealing with C. Those are the ones harder to grasp and difficult to explain to students
It might be a REAL GOOD IDEA to post the code
It's in the description ;)
Thank you
Hey, CodeVault. I'm having a hard time understanding this topic.
In 11:37 you say if I dereference a 2D Array I'll get just the first integer of the matrix, but when I done that in my main() function actually what I get is an error, because it expects an variable of type array, with is true because matrix[0] have an array.
I really don't get that part, why *matrix works differentelly in a function parameter and main.
Arrays have a lot of "syntactic sugar" around them.
When you define an array:
int arr[10][10];
This is actually just 100 integers one after the other in memory and nothing else.
But when you pass it as double pointer to a function:
fun(int** arr);
This assumes you have an array of pointers to arrays of int. And the memory layout for that is completely different.
So, when you have a 2D array you have to pass it as a single pointer and dereference it accordingly:
void fun(int* arr) {
arr[i * 10 + j]; // i-th row, j-th column
}
When it's in main, the compiler does that automatically for you:
int arr[10][10];
arr[i][j]; // this is the same dereference as the one in the function
@@CodeVault love you
Simply superb!
7:38 blew my mind
Can you also explain about dynamically allocated arrays as parameters?
Yeah, but those are just simple pointers
thanks for the video
Thank you for the video! I just have one question, why do you have to convert the two dimensional array to an integer pointer in the main function before passing it to the function, I thought that an array becomes an integer pointer anyway when getting passed to a function?
That's true, you don't have to cast that parameter there. But since I was casting a 2d array to a pointer, the compiler would give me a warning which I didn't want
@@CodeVaultThank you!
What about passing the length of the second dimension as an argument in a function definition?
Yes! That's usually how you have to pass any arrays as parameters
Thank you
Sir , an array declared in heap using malloc is global or not, as it retains in memory even after function returns , so can we edit it in any other function without passing as argument instead simply calling inside the fun by the ptr name
plz reply @ earliest of ur convience
Well... it's accessible from anywhere. But you still need a variable in function you want to use it that contains the address to that array. Otherwise you cannot just access it if its pointer is stored in another function.
void functiona() {
int arr = malloc(sizeof(int) * 5);
}
void functionb() {
arr[0] = 5; // ERROR: Undefined variable arr
}
int main() {
functiona();
functionb();
return 0;
}
So the memory you allocated in functiona is still there BUT you don't have access to it in functionb because you also need a pointer to it. And that pointer is local to functiona right now
Thanks alot
Is there a way to identify the type of var like whether it is char* or char**
Like whethere ther exist something like typeof() operator in python
my brain hurts
What about string array..?
It will behave the exact same but only on the base (double) pointer
I think you can just do something like... without the cast
void printArr(int *arrArg) {
printf(" arg[0][2] : %d",(arrArg[0]+2));
}
int main(void) {
int arr[][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
};
printArr(arr);
}