2D Array Confusion (C program) - c

I have a 2D array, lets call it "A1".
A1[rows][cols].
later in my program I create another 2D array called "A2",
A2[new_rows][new_cols]
A2 is bigger than A1... is there any way for me to set A1 the same size & contents of A2?

Arrays are static in C, so unfortunately you cannot change the size of an array once you define it. You can, however, achieve what you speak of using dynamically allocated arrays (although, this isn't strictly the same as resizing an array since, when reallocating, you lose the reference to the original array). Start by creating two dynamically allocated arrays A1 and A2 using malloc. Next, use realloc to reallocate A1 to be the same size as A2. Finally, copy the contents of A2 to A1. This will effectively "resize" A1 to be the same size as A2 with the same contents as A2. Here is some sample code (you may use whatever populating method is right for you, I just used filler):
#include <stdio.h>
#include <stdlib.h>
int **make2DArray(int rows, int cols);
void populate2DArray(int **array, int rows, int cols);
void print2DArray(int **array, int rows, int cols);
int main(int argc, char **argv)
{
int i, j;
int rows = 2, cols = 3;
int newRows = 4, newCols = 7;
// Create two dynamic arrays.
int **A1 = make2DArray(rows, cols);
int **A2 = make2DArray(newRows, newCols);
// Populate the dynamic arrays (however you like).
populate2DArray(A1, rows, cols);
populate2DArray(A2, newRows, newCols);
// Print original arrays.
printf("A1 (before):\n");
print2DArray(A1, rows, cols);
printf("\nA2 (before):\n");
print2DArray(A2, newRows, newCols);
// Reallocate A1 to be same size as A2.
int **temp = realloc(A1, sizeof(int *) * newRows);
if (temp)
{
A1 = temp;
int *tempRow;
for (i = 0; i < newRows; i++)
{
tempRow = realloc(A1[i], sizeof(int) * newCols);
if (tempRow)
{
A1[i] = tempRow;
}
}
}
// Copy contents of A2 to A1.
for (i = 0; i < newRows; i++)
{
for (j = 0; j < newCols; j++)
{
A1[i][j] = A2[i][j];
}
}
// Print resized A1 (should be same as A2).
printf("\nA1 (after):\n");
print2DArray(A1, newRows, newCols);
printf("\nA2 (after):\n");
print2DArray(A2, newRows, newCols);
}
int **make2DArray(int rows, int cols) {
// Dynamically allocate a 2D array.
int **array = malloc(sizeof(int *) * rows);
if (array)
{
for (int i = 0; i < rows; i++)
{
array[i] = malloc(sizeof(int) * cols);
}
}
return array;
}
void populate2DArray(int **array, int rows, int cols) {
// Populate a 2D array (whatever is appropriate).
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
array[i][j] = i + j;
}
}
}
void print2DArray(int **array, int rows, int cols)
{
// Print a 2D array to the terminal.
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
}
The output to the following code will be:
A1 (before):
0 1 2
1 2 3
A2 (before):
0 1 2 3 4 5 6
1 2 3 4 5 6 7
2 3 4 5 6 7 8
3 4 5 6 7 8 9
A1 (after):
0 1 2 3 4 5 6
1 2 3 4 5 6 7
2 3 4 5 6 7 8
3 4 5 6 7 8 9
A2 (after):
0 1 2 3 4 5 6
1 2 3 4 5 6 7
2 3 4 5 6 7 8
3 4 5 6 7 8 9

Related

How would I go about reversing a 2D array in C?

Let's say my array looks like this. The number of rows will always match the number of columns in this program.
[0] [1] [2]
[3] [4] [5]
[6] [7] [8]
I would need to turn this into the reversed form:
[2] [1] [0]
[5] [4] [3]
[8] [7] [6]
I know that multidimensional arrays are just arrays of arrays, which hopefully shortens the scale of my question to just reversing a 1D array, but I don't know how to apply that same idea to a 2D array. The size will not always be a 3 by 3 array, but again the rows and columns will always be the same number.
Try following code, here n is the number of rows and m is the number of columns. Hopefully this will solve your problem. Happy coding!
for(i = 0; i < n; i++) {
for(j = 0; j < m/2; j++) {
int temp = arr[i][j];
arr[i][j] = arr[i][m-j-1];
arr[i][m-j-1] = temp;
}
}
If you are looking for a function to reverse 2D array, then you can use a function declaration like this: void reverse_2d_arr(int , int (*)[]);
where,
void reverse_2d_arr(int size, int arr[size][size]) {
int i = 0, j, k, temp;
while(i < size) {
j = 0;
k = size - 1;
while(j < k) {
temp = arr[i][j];
arr[i][j] = arr[i][k];
arr[i][k] = temp;
k--;
j++;
}
i++;
}
}
and call it using, reverse_2d_arr(3, arr); where arr is your 2d array and 3 its size.
Using Standard Arrays
From an efficiency standpoint, swap two-elements per-iteration when iterating over the column values. Since your array has a fixed width, start with the beginning and end elements, swap them, and continue working from the end to the middle, e.g.
void rev2d (int (*a)[COLS], int rows, int cols)
{
for (int i = 0; i < rows; i++)
for (int j = 0, k = cols - 1; j < k; j++, k--) {
int tmp = a[i][j];
a[i][j] = a[i][k];
a[i][k] = tmp;
}
}
(above the ..[j] and ..[k] elemnts are each swapped per-iteration of the inner-loop)
Or if you wanted to do the same thing using while loops and pointers to the beginning and end elements in each row (aside from iterating over the rows in reverse), you could do the following:
void rev2dptrs (int (*a)[COLS], int rows, int cols)
{
while (rows--) {
int *beg = *(a + rows), *end = *(a + rows) + cols - 1;
while (end > beg) {
int tmp = *beg;
*beg++ = *end;
*end-- = tmp;
}
}
}
In each case, for example if you had:
#define ROWS 3
#define COLS ROWS
...
int a[][COLS] = {{ 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }};
Your function call would be:
rev2d (a, ROWS, COLS);
or in the second case:
rev2dptrs (a, ROWS, COLS);
Just a twist on a normal reversal.
Using Variable Length Arrays
The original intent was to avoid examples with VLA due to C11 Standard - 6.7.6.2 Array declarators(p4) "Variable length arrays are a conditional feature that implementations need not support;" and C11 Standard - 6.10.8.3 Conditional feature macros __STDC_NO_VLA__
However as pointed out in the comments, and with the real-world practicality that virtually all major compilers will continue to provide VLA, you can provide a bit more flexibility by reversing the declarations and specifying the rows and cols sizes fist and then passing the array as a VLA. The benefit is that it frees you from a constant size. For example, but functions can be re-written passing the array as a VLA:
void rev2dvla (int rows, int cols, int a[rows][cols])
{
for (int i = 0; i < rows; i++)
for (int j = 0, k = cols - 1; j < k; j++, k--) {
int tmp = a[i][j];
a[i][j] = a[i][k];
a[i][k] = tmp;
}
}
and with pointers:
void rev2dptrsvla (int rows, int cols, int a[rows][cols])
{
while (rows--) {
int *beg = *(a + rows),
*end = *(a + rows) + cols - 1;
while (end > beg) {
int tmp = *beg;
*beg++ = *end;
*end-- = tmp;
}
}
}
Here, the benefit is you are freed from the integer constant constraint on the number of elements per-row. By specifying the rows and cols parameters before the array parameter, the rows and cols values are known before the array int a[rows][cols] is specified as a parameter allowing the VLA to be a complete type.
The function calls would then be:
rev2dvla (rows, COLS, a);
and
rev2dptrsvla (rows, COLS, a);
If you understand each of the ways and how they differ from the others -- then you have sorting a 2D array under control. Let me know if you have further questions.
Putting the full example together to exercise each function above at least once and adding a print2D function, you could do something like the following:
#include <stdio.h>
#define COLS 3
void rev2d (int (*a)[COLS], int rows, int cols)
{
for (int i = 0; i < rows; i++)
for (int j = 0, k = cols - 1; j < k; j++, k--) {
int tmp = a[i][j];
a[i][j] = a[i][k];
a[i][k] = tmp;
}
}
void rev2dptrs (int (*a)[COLS], int rows, int cols)
{
while (rows--) {
int *beg = *(a + rows),
*end = *(a + rows) + cols - 1;
while (end > beg) {
int tmp = *beg;
*beg++ = *end;
*end-- = tmp;
}
}
}
void rev2dvla (int rows, int cols, int a[rows][cols])
{
for (int i = 0; i < rows; i++)
for (int j = 0, k = cols - 1; j < k; j++, k--) {
int tmp = a[i][j];
a[i][j] = a[i][k];
a[i][k] = tmp;
}
}
void rev2dptrsvla (int rows, int cols, int a[rows][cols])
{
while (rows--) {
int *beg = *(a + rows),
*end = *(a + rows) + cols - 1;
while (end > beg) {
int tmp = *beg;
*beg++ = *end;
*end-- = tmp;
}
}
}
void prn2d (int (*a)[COLS], int rows, int cols)
{
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++)
printf (" %2d", a[i][j]);
putchar ('\n');
}
}
int main (void) {
int a[][COLS] = {{ 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }},
rows = sizeof *a / sizeof **a;
puts ("original:");
prn2d (a, rows, COLS); /* print original */
rev2d (a, rows, COLS); /* reverse col values using indexes */
puts ("\nreversed using indexes:");
prn2d (a, rows, COLS); /* print reversed array */
rev2dptrs (a, rows, COLS); /* reverse reversed array to restore original */
puts ("\nrestore original using pointers:");
prn2d (a, rows, COLS); /* print original */
rev2dptrs (a, rows, COLS); /* reverse col values using pointers */
puts ("\nreverse again using pointers:");
prn2d (a, rows, COLS); /* print reversed array */
rev2dvla (rows, COLS, a); /* reverse col values restoring original */
puts ("\nrestore original using VLA w/indexes:");
prn2d (a, rows, COLS); /* print original */
rev2dvla (rows, COLS, a); /* reverse col values using indexes */
puts ("\nreversed with VLA using indexes:");
prn2d (a, rows, COLS); /* print reversed array */
rev2dptrsvla (rows, COLS, a); /* reverse reversed array to restore original */
puts ("\nrestore original using VLA w/pointers:");
prn2d (a, rows, COLS); /* print original */
rev2dptrsvla (rows, COLS, a); /* reverse col values using pointers */
puts ("\nreverse again using VLA w/pointers:");
prn2d (a, rows, COLS); /* print reversed array */
}
Example Use/Output
$ ./bin/revarr2d
original:
0 1 2
3 4 5
6 7 8
reversed using indexes:
2 1 0
5 4 3
8 7 6
restore original using pointers:
0 1 2
3 4 5
6 7 8
reverse again using pointers:
2 1 0
5 4 3
8 7 6
restore original using VLA w/indexes:
0 1 2
3 4 5
6 7 8
reversed with VLA using indexes:
2 1 0
5 4 3
8 7 6
restore original using VLA w/pointers:
0 1 2
3 4 5
6 7 8
reverse again using VLA w/pointers:
2 1 0
5 4 3
8 7 6

How to initialize an array of arrays with non-constant length?

I am trying to make an array which contains 1D arrays of varying length. Due to the variation in length, I cannot use a 2D array. My code is as follows:
int ROW = 6;
int COL = 4;
int faceverts[6][4] = {{3,2,1,0}, {4,5,1,0}, {2,6,5,1}, {2,3,5,6}, {7,3,0,4}, {1,6,7,4}};
int (*q)[4] = faceverts;
int main(){
for (int i = 0; i < ROW; i++){
for (int k = 0; k < COL; k++)
printf("%d ", *(*(q+i)+k));
printf("\n");
}
}
My goal is to be able to get rid of those ROW and COL variables, as well as not have a fixed 2D array, but rather an array of 1D arrays of varying length. I have been told that using pointers is key to doing this task, but I do not know how to do this myself.
One approach is to create an array of structures. Each structure element contains a pointer and count to an array.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *a;
size_t n;
} TwoD;
#define AN(a) (sizeof (a)/sizeof (a)[0])
int smallest[1] = { 1 };
int smaller[2] = { 2, 3 };
int small[3] = { 4, 5, 6 };
int big[4] = { 7, 8, 9, 10 };
int bigger[5] = { 11, 12, 13, 14, 15 };
int biggest[6] = { 16, 17, 18, 19, 20, 21 };
TwoD faceverts[6] = {
{ smallest, AN(smallest) }, { smaller, AN(smaller) }, { small, AN(small) },
{ big, AN(big) }, { bigger, AN(bigger) }, { biggest, AN(biggest) } };
int main(void) {
// Let us change things a bit at run time
int change[] = { 22,23,24,25,26,27,28 };
faceverts[0] = (TwoD) {change, AN(change)}; // compound literal
for (size_t row = 0; row < AN(faceverts); row++) {
for (size_t col = 0; col < faceverts[row].n; col++) {
printf(" %d", faceverts[row].a[col]);
}
printf("\n");
}
return 0;
}
Output
22 23 24 25 26 27 28
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21
There is only 1D array in memory. (2D array is actually a long 1D array)
Allocate a 2D array (rows, cols)
int *arr;
int size;
size = width * height;
arr = (int *) malloc(sizeof(int) * size);
Access element (x, y) in the array
int e;
int offset;
offset = x * cols + y;
e = *(arr + offset);
Free the array
free(arr);
Allocate a irregular 2D array (col_0, col_2, ...., col_n-1);
int arr;
int size = 0;
// size = col_0 + ... + col_n-1;
arr = (int *) malloc(sizeof(int) * size);
Access element (x_row, y_col) in the array
int e;
int offset;
// offset = col_1 + ... + col_x-1 + y_col;
e = *(arr + offset);

Something wrong with different IDE xcode and vs

I am using both Xcode and VS2017.But the code below works fine in Xcode,and get right output.But in vs, when using the function Printlist(),it stop working and run into loop:
Please input the number of vertexes:
5
Please input the number of edges:
6
Please input each vertex's imformation:
A
B
C
D
E
Please input the relationship between two vertexes:
A B
A D
B C
C D
B E
C E
The Adjacency Matrix you've entered is:
0 1 0 1 0
1 0 1 0 1
0 1 0 1 1
1 0 1 0 0
0 1 1 0 0
The converted adjacency list is:
(0)A->3 1
(1)B->4 2 0
(2)->4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4 3 4................
The program is to create an adjacency matrix and convert it to list. I am searching for a long time on net. But no use. Please help or try to give some ideas how to achieve this.
Thanks in advance:)
#include <stdio.h>
#include <stdlib.h>
#define vexnum 20
#define isLetter(a) ((((a)>='a')&&((a)<='z')) || (((a)>='A')&&((a)<='Z')))
int visited[vexnum];
typedef struct {
char vexs[vexnum];
int AdjMatrix[vexnum][vexnum];
int n, e; //VEXNUM and EDGENUM
}MGraph;
typedef struct ArcNode
{
int adjvex;
struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode
{
char data;
ArcNode *firstarc;
}VNode, AdjList[vexnum];
int GetPosition(MGraph G, char ch)
{
int i;
for (i = 0; i<G.n; i++)
{
if (G.vexs[i] == ch)
return i;
}
return -1;
}
void CreatMGraph(MGraph *G, int n, int e)
{
int i, j, k;
int p = 0, q = 0;
char a, b;
printf("Please input each vertex's imformation:\n");
for (i = 0; i<n; i++)
{
do
{
G->vexs[i] = getchar();
} while (!isLetter(G->vexs[i]));
}
for (i = 0; i<n; i++)
{
for (j = 0; j<n; j++)
{
G->AdjMatrix[i][j] = 0;
}
}
printf("Please input the relationship between two vertexes:\n");
for (k = 0; k<G->e; k++)
{
do
{
a = getchar();
} while (!isLetter(a));
do
{
b = getchar();
} while (!isLetter(b));
p = GetPosition(*G, a);
q = GetPosition(*G, b);
G->AdjMatrix[p][q] = G->AdjMatrix[q][p] = 1;
}
}
void PrintAdjMatrix(MGraph G)
{
int i, j;
printf("The Adjacency Matrix you've entered is:\n");
for (i = 0; i<G.n; i++)
{
for (j = 0; j<G.n; j++)
{
printf("%d ", G.AdjMatrix[i][j]);
if (j == G.n - 1)
printf("\n");
}
}
}
void MatrixToList(MGraph G, AdjList *L)
{
int i, j;
ArcNode *p;
for (i = 0; i<G.n; i++)
{
L[i]->data = G.vexs[i];
L[i]->firstarc = NULL;
}
for (i = 0; i<G.n; i++)
{
for (j = 0; j<G.n; j++)
{
if (G.AdjMatrix[i][j] == 1)
{
if (L[i]->firstarc == NULL)
{
p = (ArcNode *)malloc(sizeof(ArcNode));
p->adjvex = j;
p->nextarc = NULL;
L[i]->firstarc = p;
}
else
{
p = (ArcNode *)malloc(sizeof(ArcNode));
p->adjvex = j;
p->nextarc = L[i]->firstarc;
L[i]->firstarc = p;
}
}
}
}
}
void Printlist(MGraph G, AdjList *L)
{
ArcNode *p;
int i;
for (i = 0; i<G.n; i++)
{
printf("(%d)%c->", i, L[i]->data);
p = (ArcNode *)malloc(sizeof(ArcNode));
p = L[i]->firstarc;
while (p)
{
printf("%d ", p->adjvex);
p = p->nextarc;
}
printf("\n");
}
}
int main()
{
MGraph G;
printf("Please input the number of vertexes:\n");
scanf("%d", &G.n);
printf("Please input the number of edges:\n");
scanf("%d", &G.e);
CreatMGraph(&G, G.n, G.e);
PrintAdjMatrix(G);
AdjList *L = NULL;
L = (AdjList *)malloc(sizeof(AdjList));
MatrixToList(G, L);
printf("The converted adjacency list is:\n");
Printlist(G, L);
return 0;
}
The subscripting of parameter L in functions MatrixToList() and Printlist() is wrong. Consider the parameter declaration AdjList *L: L is a pointer to AdjList, which in turn is defined as an array of vexnum struct VNodes, so L is a pointer to the whole array of struct VNodes. Then with an expression as L[i]->data not the ith node within the array is accessed, but the ith array of a (nonexistent for i > 0) array of arrays (and with ->data the data element in the first node of that ith array). To fix that error, you could change the parameter declaration in the mentioned functions to AdjList L as well as every instance of L[i]-> in those functions to L[i]. and call
MatrixToList(G, *L);
and
Printlist(G, *L);

Matrix copying causes segmentation fault

I must write a function in C that takes in a matrix (src) and 2 integer values(x,y), then gives out a matrix which contains src x by y times.
For example
3 5
2 1
with (2,3) is going to be
3 5 3 5
2 1 2 1
3 5 3 5
2 1 2 1
3 5 3 5
2 1 2 1
I am given the structure
struct Mat {
int cols; // number of columns
int rows; // number of rows
int** row_ptrs; // pointer to rows (the actual matrix)
} Mat;
and wrote this function:
#include "exercise_1.h"
#include <stdlib.h>
Mat* matrixRepeat(Mat* src, int num_row_blocks, int num_col_blocks)
{
Mat *newMat = malloc(sizeof(Mat));
newMat->rows = src->rows * num_row_blocks;
newMat->cols = src->cols * num_col_blocks;
newMat->row_ptrs = calloc(newMat->rows, sizeof(int*));
for(int i = 0; i < newMat->cols; i++)
newMat->row_ptrs[i] = calloc(newMat->cols, sizeof(int));
for(int i = 0; i < newMat->rows; i++)
for(int j = 0; j< newMat->cols; j++)
newMat->row_ptrs[i][j] = src->row_ptrs[i%src->rows][j%src->cols];
return newMat;
}
Then I am given some test programs: half of them works just fine, the other tough gives me segfault. I know for sure that the tests are correct, so there must be a problem in my program. Can you help me find it?
The condition in the loop
for(int i = 0; i < newMat->cols; i++)
^^^^^^^^^^^
newMat->row_ptrs[i] = calloc(newMat->cols, sizeof(int));
is wrong. There must be
for(int i = 0; i < newMat->rows; i++)
^^^^^^^^^^^
newMat->row_ptrs[i] = calloc(newMat->cols, sizeof(int));
Note: I think you mean
typedef struct Mat {
^^^^^^^
int cols; // number of columns
int rows; // number of rows
int** row_ptrs; // pointer to rows (the actual matrix)
} Mat;

Passing Pointer to Pointer to functions

void foo(double **A, double **B) {
//....
}
int main() {
double **A;
double B[10][10];
int i, j;
A = (double **)malloc(sizeof(double*) * 10);
for (i = 0; i < 10; i++) {
*(A+i) = (double*)malloc(sizeof(double) * 10);
for (j = 0; j < 10; j++) {
*(*(A+i)+j) = i * j;
}
}
foo(A, B);
return 0;
}
This gives me a warning
warning: incompatible pointer types passing 'double [10][10]' to parameter of type 'double **'
[-Wincompatible-pointer-types]
From my understanding B holds a pointer to a pointer of type double. Am I not doing the same thing with A and B. Why am I getting this warning only for B?
B is an array of arrays of 10 double, a very different type from an array of pointers to arrays of double. Change foo's prototype to:
void foo(double **A, double (*B)[10])
Also simplify the code in main this way:
int main() {
double **A;
double B[10][10];
int i, j;
A = malloc(10 * sizeof(*A));
for (i = 0; i < 10; i++) {
A[i] = malloc(10 * sizeof(*A[i]));
for (j = 0; j < 10; j++) {
A[i][j] = i * j;
}
}
foo(A, B);
return 0;
}
The primary difference between passing a pointer to array and pointer to pointer from a syntax standpoint isn't too difficult to understand. When you pass a pointer to array, either array[x][y] or (*array)[y], you specify the parameter as either:
somefunc (type array[][y])
or
somefunc (type (*array)[y])
The rule to take away -- when passing a pointer to array, you must always pass the number of columns involved.
On the other hand, when passing a pointer-to-pointer-to-type, you only need to pass a pointer. e.g.:
somefunc (type **array)
The primary difference in "Why?" has to do with how the information is stored in memory. Take for example int array[x][y]. There you have x * y integers stored in a sequential block of memory. x and y provide a direct index to an integer within that sequential block. (anywhere within the x arrays containing y values each).
On the other hand, with int **array, you have a pointer to pointer -- meaning that your array[x] value identifies points to another pointer holding the beginning address of an array of y values. There is no requirement that any of the separate pointers identified by array[0], array[1], ... be stored in any sequential manner.
Take the following example. You have array (your typical array[x][y] or 2D array as it is often referred to) and arraydp an array of pointer-to-pointer-to-type (your typical double-pointer). The example shows the different way you must handle passing each.
The tweak in the game is that a function can only return a single value (a pointer), so to return a reference to array[x][y] it must be returned as a double-pointer and recast appropriately.
#include <stdio.h>
#include <stdlib.h>
#define MAX 5
/* function prototypes */
int **alloc_fill (size_t n);
int **alloc_fill_dp (size_t n);
void prn_array (int (*a)[MAX], size_t nrow);
void prn_array_dp (int **a, size_t nrow, size_t ncol);
int main (int argc, char **argv) {
int (*array)[MAX] = { NULL }; /* pointer to array of MAX ints */
int **arraydp = NULL; /* pointer to pointer to int */
size_t i, n;
n = argc > 1 ? atoi(argv[1]) : 5; /* set number of rows */
/* fill 'n' pointer to array[MAX] */
array = (int (*)[MAX])alloc_fill (n);
/* fill 'n' pointer to pointer to int */
arraydp = alloc_fill_dp (n);
if (!array || !arraydp ) { /* validate both allocated */
fprintf (stderr, "error: alloc_fill failed.\n");
return 1;
}
printf ("\n elements of '%zu' arrays:\n\n", n);
prn_array (array, n);
printf ("\n elements of '%zu' arrays:\n\n", n);
prn_array_dp (arraydp, n, MAX);
free (array); /* single call to free for 'array' */
for (i = 0; i < n; i++) /* free each pointer, then arraydp */
free (arraydp[i]);
free (arraydp);
return 0;
}
/* allocate/fill 'n' pointer to array of MAX int */
int **alloc_fill (size_t n)
{
int (*a)[MAX] = { NULL };
size_t i, j;
if (!(a = calloc (n, sizeof **a * MAX))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return NULL;
}
for (i = 0; i < n; i++)
for (j = 0; j < MAX; j++)
a[i][j] = (i + 1) * (j + 1);
return (int **)a;
}
/* allocate/fill 'n' pointer to pointer to type int */
int **alloc_fill_dp (size_t n)
{
int **a = NULL;
size_t i, j;
/* allocate 'n' pointers */
if (!(a = calloc (n, sizeof *a))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return NULL;
}
for (i = 0; i < n; i++) {
/* allocate MAX ints */
if (!(a[i] = calloc (MAX, sizeof **a))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return NULL;
}
for (j = 0; j < MAX; j++)
a[i][j] = (i + 1) * (j + 1);
}
return a;
}
/* print function for 'nrow' pointers
* to array of 'MAX' ints
*/
void prn_array (int (*a)[MAX], size_t nrow)
{
size_t i,j;
for (i = 0; i < nrow; i++) {
for (j = 0; j < MAX; j++)
printf (" %4d", a[i][j]);
// putchar ('\n');
putchar ('\n'), putchar ('\n');
}
}
/* printf function for 'nrow' pointers
* to pointer to 'ncol' ints
*/
void prn_array_dp (int **a, size_t nrow, size_t ncol)
{
size_t i,j;
for (i = 0; i < nrow; i++) {
for (j = 0; j < ncol; j++)
printf (" %4d", a[i][j]);
// putchar ('\n');
putchar ('\n'), putchar ('\n');
}
}
Output
$ ./bin/array_ptr_to_array
elements of '5' arrays:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
elements of '5' arrays:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
Difference of Storage in Memory
Here in memory is where the rubber meets the road. I you look below, you have the debugger (gdb) depiction of the memory layout for both array and arraydp. Notice with array all values are sequential. However, with arraydp, the first 5 values are the pointer address that point to each of the respective 5 int arrays that make up the values for arraydp. If you then examine pointer address for arraydp[0-4], you then may index each of the individual values:
array in memory:
(gdb) x/25d array
0x603010: 1 2 3 4
0x603020: 5 2 4 6
0x603030: 8 10 3 6
0x603040: 9 12 15 4
0x603050: 8 12 16 20
0x603060: 5 10 15 20
0x603070: 25
arraydp in memory:
(gdb) x/49d arraydp
0x603080: 6303920 0 6303952 0
0x603090: 6303984 0 6304016 0
0x6030a0: 6304048 0 33 0
0x6030b0: 1 2 3 4
0x6030c0: 5 0 33 0
0x6030d0: 2 4 6 8
0x6030e0: 10 0 33 0
0x6030f0: 3 6 9 12
0x603100: 15 0 33 0
0x603110: 4 8 12 16
0x603120: 20 0 33 0
0x603130: 5 10 15 20
0x603140: 25
(gdb) x/5d 6303920
0x6030b0: 1 2 3 4
0x6030c0: 5
(gdb) x/5d 6303952
0x6030d0: 2 4 6 8
0x6030e0: 10
(gdb) x/5d 6303984
0x6030f0: 3 6 9 12
0x603100: 15
(gdb) x/5d 6304016
0x603110: 4 8 12 16
0x603120: 20
(gdb) x/5d 6304048
0x603130: 5 10 15 20
0x603140: 25
From a programming standpoint, the differences may seem subtle, but they are critical from a syntax standpoint. Look it over and let me know if you have further questions.
Try void foo(double **A, double B[10][10]) then pass it foo(A, B)

Resources