There are already two valuable answers above but I think you're still confused about the situation; for I felt the same while I was a rookie (though I'm not a pro yet).
- The line below does not return a pointer. Actually, it returns a memory address and the first address holds the first element of the array as data; but as it is on stack, C treats it like a pointer.
int a[4][5] = { ... };
- The lines below, again, return memory addresses on stack, but they hold other memory addresses and this time, they are literally pointers; they point to different memory addresses —most probably on the heap.
int** b = malloc(4 * sizeof(int*));
int* c = malloc(5 * sizeof(int));
Do not keep your hands clean and debug the code below and inspect the output while keeping an eye on the memory dump at the same time:
#include <stdio.h>
#include <stdlib.h>
int** copyArray(int row, int col, int pSrc[row][col]) {
int** pDst = malloc(row * sizeof(int*));
for (int i = 0; i < row; i++) {
pDst[i] = malloc(col * sizeof(int));
for (int j = 0; j < col; j++) {
pDst[i][j] = pSrc[i][j];
}
}
return pDst;
}
int main() {
int a[4][5] = { { 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 11, 12, 13, 14, 15 },
{ 16, 17, 18, 19, 20 } };
int** b = copyArray(4, 5, a);
printf("%2d %2d %2d %2d %2d\n", a[0][0], a[0][1], a[0][2], a[0][3], a[0][4]);
printf("%p\n", &a);
printf("%p\n", a);
printf("%p\n", *a);
printf("%p\n", a[0]);
printf("%p\n", &a[0]);
printf("\n");
printf("%2d %2d %2d %2d %2d\n", b[0][0], b[0][1], b[0][2], b[0][3], b[0][4]);
printf("%p\n", &b);
printf("%p\n", b);
printf("%p\n", *b);
printf("%p\n", b[0]);
printf("%p\n", &b[0]);
for (int i = 0; i < 4; i++) {
free(b[i]);
}
free(b);
return 0;
}