Why do I encounter an error on a simple matrix function - c

I don't understand why my program crashes every time I finish reading and my showing function comes....
The error says read access violation
void read(int **m, int n)
{
int i, j;
for(i=0;i<n;i++)
for (j = 0; j < n; j++)
{
printf("a[%d][%d]=", i, j);
scanf("%d", (m + i * n + j));
}
}
void show(int **m, int n)
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j <= n; j++)
{
printf("%d ", *(m + i * n + j));//where the error occurs
printf("\n");
}
}
int main()
{
int **m;
int opt,n;
printf("Introduceti nr de linii si coloane:");
scanf("%d", &n);
m= (int*)malloc(n*n * sizeof(int));

Continuing from my comment, your primary issue is you allocate storage for n * n pointers, but then fail to allocate any storage for the int values. When working with pointers and/or allocating storage dynamically, you should always be able to answer "To what valid storage do each of my pointers point?". If you can't you have no idea what address you are attempting to use.
(note: you only need to allocate n pointers -- one for each row)
As #RetiredNinja also points out, you have an Off-By-One error in for (j = 0; j <= n; j++) which attempts to read the address for n + 1 integer values per row.
Since you have allocated n * n pointers, you now need to allocate storage for n integers assigning the address for each new valid block of memory to each of your pointers in turn. Additionally, in read() since your read with scanf() or allocation with malloc() can fail, you must provide a return type for the read() function that can indicate success or failure. Making the return type int and returning 1 on success or 0 on failure is fine.
(note: since read() conflicts with an existing syscall name, you should rename your read() function, e.g. mtrxread() or the like)
Putting that altogether, you can do something like:
/* type must be capable of indicating success/failure */
int mtrxread (int **m, int n)
{
int i, j;
for (i = 0; i < n; i++) { /* guard each block with {...} */
/* allocate n int / validate EVERY allocation */
if (!(m[i] = malloc (n * sizeof *m[i]))) {
perror ("malloc-m[i]");
return 1;
}
for (j = 0; j < n; j++) {
printf("a[%d][%d] = ", i, j);
if (scanf ("%d", &m[i][j]) != 1) { /* validate EVERY input */
fputs ("error: invalid integer input.\n", stderr);
return 0;
}
}
}
return 1;
}
(note: In C, there is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?)
(also fix the <= making it < in show())
In main(), you need to validate EVERY input and EVERY allocation - just as you do everywhere else. You also need to validate whether mtrxread() succeeds or fails. Putting that together, you can do:
int main (void) {
int **m; /* NOT an array, a pointer-to-pointer-to int */
int n;
fputs ("Introduceti nr de linii si coloane: ", stdout);
if (scanf("%d", &n) != 1) { /* validate EVERY input */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
/* validate EVERY allocation */
if (!(m = malloc (n * sizeof *m))) {
perror ("malloc-m");
return 1;
}
if (!mtrxread (m, n)) { /* validate read of elements */
return 1;
}
show (m, n); /* show the matrix */
for (int i = 0; i < n; i++) {
free (m[i]); /* free int storage */
}
free (m); /* free pointers */
}
(note: the additional information provided by comments in the code)
The complete code could be:
#include <stdio.h>
#include <stdlib.h>
/* type must be capable of indicating success/failure */
int mtrxread (int **m, int n)
{
int i, j;
for (i = 0; i < n; i++) { /* guard each block with {...} */
/* allocate n int / validate EVERY allocation */
if (!(m[i] = malloc (n * sizeof *m[i]))) {
perror ("malloc-m[i]");
return 1;
}
for (j = 0; j < n; j++) {
printf("a[%d][%d] = ", i, j);
if (scanf ("%d", &m[i][j]) != 1) { /* validate EVERY input */
fputs ("error: invalid integer input.\n", stderr);
return 0;
}
}
}
return 1;
}
void show (int **m, int n)
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%d ", m[i][j]);//where the error occurs
}
putchar ('\n'); /* you putchar() a single character */
}
}
int main (void) {
int **m; /* NOT an array, a pointer-to-pointer-to int */
int n;
fputs ("Introduceti nr de linii si coloane: ", stdout);
if (scanf("%d", &n) != 1) { /* validate EVERY input */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
/* validate EVERY allocation */
if (!(m = malloc (n * sizeof *m))) {
perror ("malloc-m");
return 1;
}
if (!mtrxread (m, n)) { /* validate read of elements */
return 1;
}
show (m, n); /* show the matrix */
for (int i = 0; i < n; i++) {
free (m[i]); /* free int storage */
}
free (m); /* free pointers */
}
Example Use/Output
$ ./bin/ptr2ptr2int-allocate
Introduceti nr de linii si coloane: 3
a[0][0] = 1
a[0][1] = 2
a[0][2] = 3
a[1][0] = 4
a[1][1] = 5
a[1][2] = 6
a[2][0] = 7
a[2][1] = 8
a[2][2] = 9
1 2 3
4 5 6
7 8 9
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to ensure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/ptr2ptr2int-allocate
==5081== Memcheck, a memory error detector
==5081== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5081== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==5081== Command: ./bin/ptr2ptr2int-allocate
==5081==
Introduceti nr de linii si coloane: 3
a[0][0] = 1
a[0][1] = 2
a[0][2] = 3
a[1][0] = 4
a[1][1] = 5
a[1][2] = 6
a[2][0] = 7
a[2][1] = 8
a[2][2] = 9
1 2 3
4 5 6
7 8 9
==5081==
==5081== HEAP SUMMARY:
==5081== in use at exit: 0 bytes in 0 blocks
==5081== total heap usage: 6 allocs, 6 frees, 2,156 bytes allocated
==5081==
==5081== All heap blocks were freed -- no leaks are possible
==5081==
==5081== For lists of detected and suppressed errors, rerun with: -s
==5081== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Option For Single-Allocation/Single-Free with Pointer to VLA
C provides a, now optional, feature called a Variable Length Array, that in your case can provide a single-allocation/single-free. While this feature was made optional in C11, it will remain widely supported for some time. By using a pointer-to-VLA-of int[n], you can make a single call to malloc() in main() to allocate all storage required. The changes required are:
int main (void) {
int n;
fputs ("Introduceti nr de linii si coloane: ", stdout);
if (scanf("%d", &n) != 1) { /* validate EVERY input */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
int (*m)[n]; /* pointer to VLA of n int */
/* validate EVERY allocation */
if (!(m = malloc (n * sizeof *m))) {
perror ("malloc-m");
return 1;
}
if (!mtrxread (n, m)) { /* validate read of elements */
return 1;
}
show (n, m); /* show the matrix */
free (m); /* free allocated memory */
}
The order of your parameters for each function will need to change so the size n is known before the pointer to VLA is provided. For example mtrxread() would reduce to:
/* type must be capable of indicating success/failure */
int mtrxread (int n, int (*m)[n])
{
int i, j;
for (i = 0; i < n; i++) { /* guard each block with {...} */
for (j = 0; j < n; j++) {
printf("a[%d][%d] = ", i, j);
if (scanf ("%d", &m[i][j]) != 1) { /* validate EVERY input */
fputs ("error: invalid integer input.\n", stderr);
return 0;
}
}
}
return 1;
}
(change the order for show() in like manner)
Now all memory is allocated at once and requires only a single call to free(). Quite convenient, but with the caveat of the VLA now having optional support from compilers.
Let me know if you have further questions.

Related

Matrix (2d array) and its values is not written into txt file correctly

In my program, I enable the user to decide the dimensions of their matrix and then input each cell's value in the matrix. This matrix is then saved to a .txt file as binary data. Sometimes, with certain matrices of certain values and dimensions, the matrix is not read back properly with the correct values in the correct cells.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int numberOfMatrices = 0;
int orderedMatricesInfo[100][1][2];
int matrixRows = 0;
int matrixCols = 0;
int** initMatrix(int rows, int cols);
void saveMatrix(int** matrix, int rows, int cols);
void* allocateMatrix(int rows, int cols);
int** readMatrix(int rows, int cols, int matrix[matrixRows][matrixCols], int matrixNum);
void displayMatrices();
void displayMatrix(int rows, int cols, int** matrix);
int main()
{
int n, m;
int** matrixPointer;
printf("Please enter the number of rows in your matrix: \n");
scanf("%d", &n);
printf("Please enter the number of columns in your matrix: \n");
scanf("%d", &m);
matrixPointer = initMatrix(n, m);
printf("%d\n", matrixPointer[0][0]);
displayMatrices();
printf("SUCCESS");
}
int** initMatrix(int rows, int cols)
{
int matrix[rows][cols];
int **matrixPointer;
matrixPointer = malloc(sizeof(int*)*cols);
for (int i =0; i < cols; ++i)
{
matrixPointer[i] = malloc(sizeof(int*)*cols);
}
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
printf("\nPlease enter element for [%d][%d]: \n", i, j);
scanf("%d", &matrixPointer[i][j]);
}
}
++numberOfMatrices;
orderedMatricesInfo[numberOfMatrices-1][0][0] = rows;
orderedMatricesInfo[numberOfMatrices-1][0][1] = cols;
allocateMatrix(rows, cols);
saveMatrix(matrixPointer, rows, cols);
return matrixPointer;
}
void saveMatrix(int** matrix, int rows, int cols)
{
char fullFileName[100] = "matrix";
char fileNameExtension[100] = ".txt";
char strNum[100];
sprintf(strNum, "%d", numberOfMatrices);
strcat(strNum, fileNameExtension);
strcat(fullFileName, strNum);
FILE *file = fopen(fullFileName, "ab");
for(int i=0; i<rows; ++i)
{
fwrite(matrix[i], sizeof(int), rows, file);
}
fclose(file);
}
void* allocateMatrix(int rows, int cols)
{
return malloc(sizeof(int[rows][cols]));
}
int** readMatrix(int rows, int cols, int matrix[matrixRows][matrixCols], int matrixNum)
{
int **matrixPointer;
matrixPointer = malloc(sizeof(int*)*cols);
for (int i =0; i < cols; ++i)
{
matrixPointer[i] = malloc(sizeof(int*)*cols);
}
char fullFileName[100] = "matrix";
char fileNameExtension[100] = ".txt";
char strNum[100];
sprintf(strNum, "%d", matrixNum);
strcat(strNum, fileNameExtension);
strcat(fullFileName, strNum);
FILE *file;
file=fopen(fullFileName, "rb");
fread(matrix, sizeof(int[rows][cols]), 1, file); // read 1 2D-array
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
matrixPointer[i][j] = matrix[i][j];
printf("%d", matrixPointer[i][j]);
}
}
allocateMatrix(rows, cols);
return matrixPointer;
}
void displayMatrices()
{
for (int matrixNum = 1; matrixNum <= numberOfMatrices; ++matrixNum)
{
char fullFileName[100] = "matrix";
char fileNameExtension[100] = ".txt";
char strNum[100];
sprintf(strNum, "%d", matrixNum);
strcat(strNum, fileNameExtension);
strcat(fullFileName, strNum);
matrixRows = orderedMatricesInfo[matrixNum -1][0][0];
matrixCols = orderedMatricesInfo[matrixNum -1][0][1];
int matrix[matrixRows][matrixCols];
int** matrixPointer;
matrixPointer = readMatrix(matrixRows, matrixCols, matrix, matrixNum);
printf("matrix %d", matrixNum);
displayMatrix(matrixRows, matrixCols, matrixPointer);
}
}
void displayMatrix(int rows, int cols, int** matrix)
{
for (int i = 0; i < rows; ++i)
{
printf("\n");
for (int j = 0; j < cols; ++j)
{
printf("%d ", matrix[i][j]);
}
}
printf("\n");
}
In the main function, when the user creates the matrix, the matrix is saved in a newly created file named "matrix1.txt" as binary data. However, it is not stored properly I think as when read back, the matrix is not shown correctly with the correct values.
For example, if I create a matrix:
[12, 19, 17, 15,
120, 566, 214, 153,
124, 1, 2, 3]
And then attempt to display the matrix then the matrix above is not shown, instead this is shown:
[12, 19, 17, 120,
566, 214, 124, 1,
2, 0, 101792956, 1]
Have I assigned memory incorrectly into this program? What would the problem be? As it does manage to get the first 3 elements of the top row retrieved and shown correctly. I am new to C so I cannot pinpoint the problem. When the matrix is smaller like a 2x2 matrix, then it works fine...
Thank you!
Your code is still missing information, but your initMatrix() function has a large number of small issues. You use cols where rows should be used to allocate pointers. You fail to validate any of the allocations or user-inputs. That is a recipe for Undefined Behavior. Additionally, you don't provide the code to determine what numberOfMatrices is, or how orderedMatricesInfo is declared. With those caveats noted, you can fix the immediate errors in initMatrix() with the following:
int **initMatrix(int rows, int cols)
{
int matrix[rows][cols];
int **matrixPointer;
/* allocate rows number of pointers */
matrixPointer = malloc (sizeof *matrixPointer * rows);
if (!matrixPointer) { /* validate EVERY allocation */
perror ("malloc-*matrixPointer");
return NULL;
}
/* you must allocate rows number of cols * sizeof(int) blocks
* assigning the starting address to each of your allocated pointers.
* (always use the dereferenced pointer to set type-size)
*/
for (int i = 0; i < rows; ++i)
{ /* use calloc on rows to initialize all bytes zero */
matrixPointer[i] = calloc (sizeof *matrixPointer[i], cols);
if (!matrixPointer[i]) { /* validate EVERY allocation */
perror ("calloc-matrixPointer[i]");
while (i--) /* on error, free prior memory */
free (matrixPointer[i]);
free (matrixPointer);
return NULL;
}
}
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
while (1) { /* loop continually until valid integer provided */
printf ("\nPlease enter element for [%d][%d]: \n", i, j);
/* validate EVERY user-input */
if (scanf("%d", &matrixPointer[i][j]) == 1)
break;
fputs (" error: invalid integer input.\n", stderr);
}
}
}
/* your code does not provide information on the following */
++numberOfMatrices;
orderedMatricesInfo[numberOfMatrices-1][0][0] = rows;
orderedMatricesInfo[numberOfMatrices-1][0][1] = cols;
allocateMatrix(rows, cols); /* why allocate -- that's what you just did?? */
saveMatrix(matrixPointer, rows, cols);
return matrixPointer;
}
(untested since your code is incomplete. The code is commented explaining the additions)
Note, your allocateMatrix(int rows, int cols) simply leaks memory. The return isn't assigned to any pointer so you have lost the beginning address to the allocated block with no way to free it.
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
Let me know if you have questions and please provide A Minimal, Complete, and Verifiable Example (MCVE) for further assistance.
Further Update on Errors
The remainder of your code has the same rows and cols problem where you attempt to allocate cols number of pointers (instead of rows number of pointers). However, the problem leading to your SEGFAULT was due to numberOfMatrices and the file you attempt to open being off-by-one. This was resolved by assuring your loops are consistently indexing 0 < numberOfMatrices and accommodating the file number with:
matrixPointer = readMatrix(matrixRows, matrixCols, matrix, matrixNum + 1);
Adding 1 to the matrixNum passed to readMatrix. That is a simple way to keep the numbering straight. You code writes and reads the file correctly, but note you are Appending to the file, so you will have to further work to access each of the matricies stored in your output file (you should write the number of rows and cols to the file before each matrix is written, so you can read the file back in, reading the 2 int values to determine the size of the matrix that follows -- that is left to you.
As it sits, your display function will read the file assuming the first integers in the file are for the current matrix -- which isn't the case. The integer values read to display are the elements for the first matrix that was written to the file, which will not be the same as the current matrix values unless you are writing and reading the first set of values. Otherwise, the current matrix values are contained in the file after the bytes for all previous matricies that were written to the file. A more useful file format would be:
no_matricies rows cols ...... rows cols ......
Where the first integer value written contains the number of matricies written to the file, followed by the row, col and .... data for each matrix which would allow all matricies to be accessed and allow the first integer value in the file to be updated without re-writing the entire file. (that too is left for you to consider)
Your cleaned-up code is as follows. Note: I changed your use of sprintf and eliminated the unnecessary concatenation. I also simplified copying from matrix to matrixPointer using memcpy():
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int numberOfMatrices = 0;
int orderedMatricesInfo[100][1][2];
int matrixRows = 0;
int matrixCols = 0;
int** initMatrix(int rows, int cols);
void saveMatrix(int** matrix, int rows, int cols);
void* allocateMatrix(int rows, int cols);
int** readMatrix(int rows, int cols, int matrix[matrixRows][matrixCols], int matrixNum);
void displayMatrices();
void displayMatrix(int rows, int cols, int** matrix);
int main()
{
int n, m;
int** matrixPointer;
printf("Please enter the number of rows in your matrix: \n");
if (scanf("%d", &n) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
printf("Please enter the number of columns in your matrix: \n");
if (scanf("%d", &m) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
matrixPointer = initMatrix(n, m);
// printf("%d\n", matrixPointer[0][0]);
displayMatrices();
printf("SUCCESS");
}
int **initMatrix(int rows, int cols)
{
int **matrixPointer;
/* allocate rows number of pointers */
matrixPointer = malloc (sizeof *matrixPointer * rows);
if (!matrixPointer) { /* validate EVERY allocation */
perror ("malloc-*matrixPointer");
return NULL;
}
/* you must allocate rows number of cols * sizeof(int) blocks
* assigning the starting address to each of your allocated pointers.
* (always use the dereferenced pointer to set type-size)
*/
for (int i = 0; i < rows; ++i)
{ /* use calloc on rows to initialize all bytes zero */
matrixPointer[i] = calloc (sizeof *matrixPointer[i], cols);
if (!matrixPointer[i]) { /* validate EVERY allocation */
perror ("calloc-matrixPointer[i]");
while (i--) /* on error, free prior memory */
free (matrixPointer[i]);
free (matrixPointer);
return NULL;
}
}
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
while (1) { /* loop continually until valid integer provided */
printf ("\nPlease enter element for [%d][%d]: \n", i, j);
/* validate EVERY user-input */
if (scanf("%d", &matrixPointer[i][j]) == 1)
break;
fputs (" error: invalid integer input.\n", stderr);
}
}
}
/* move numberOfMatrices++ below the assignment */
orderedMatricesInfo[numberOfMatrices][0][0] = rows;
orderedMatricesInfo[numberOfMatrices][0][1] = cols;
numberOfMatrices++;
// allocateMatrix(rows, cols); /* why allocate -- that's what you just did?? */
saveMatrix(matrixPointer, rows, cols);
return matrixPointer;
}
void saveMatrix(int** matrix, int rows, int cols)
{
char fullFileName[256];
sprintf (fullFileName, "matrix-%02d.txt", numberOfMatrices);
FILE *file = fopen(fullFileName, "ab");
if (!file) { /* validate file open for writing */
perror ("fopen-file");
return;
}
for(int i=0; i<rows; ++i)
{
fwrite(matrix[i], sizeof *matrix[i], cols, file);
}
if (fclose(file) == EOF) /* always validate close after write */
perror ("fclose-file");
}
void *allocateMatrix(int rows, int cols)
{
return malloc(sizeof(int[rows][cols]));
}
int **readMatrix(int rows, int cols, int matrix[matrixRows][matrixCols], int matrixNum)
{
int **matrixPointer;
matrixPointer = malloc(sizeof *matrixPointer * rows); /* rows not cols!! */
if (!matrixPointer) { /* validate EVERY allocation */
perror ("malloc-*matrixPointer");
return NULL;
}
for (int i =0; i < rows; ++i) /* rows not cols!! */
{
matrixPointer[i] = calloc (sizeof *matrixPointer[i], cols);
if (!matrixPointer[i]) { /* validate EVERY allocation */
perror ("calloc-matrixPointer[i]");
while (i--) /* on error, free prior memory */
free (matrixPointer[i]);
free (matrixPointer);
return NULL;
}
}
char fullFileName[256];
sprintf (fullFileName, "matrix-%02d.txt", matrixNum);
FILE *file = fopen(fullFileName, "rb");
if (!file) { /* validate file open for reading */
perror ("fopen-file");
for (int i = 0; i < rows; i++) /* on error free memory */
free (matrixPointer[i]);
free (matrixPointer);
return NULL;
}
/* validate EVERY input */
if (fread (matrix, sizeof(int[rows][cols]), 1, file) < 1) { // read 1 2D-array
for (int i = 0; i < rows; i++) /* on error free memory */
free (matrixPointer[i]);
free (matrixPointer);
return NULL;
}
for (int i = 0; i < rows; ++i)
{
memcpy (matrixPointer[i], matrix[i], sizeof *matrixPointer[i] * cols);
/*
for (int j = 0; j < cols; ++j)
{
matrixPointer[i][j] = matrix[i][j];
printf("%d", matrixPointer[i][j]);
}
*/
}
// allocateMatrix(rows, cols); /* not needed */
return matrixPointer;
}
void displayMatrices()
{
for (int matrixNum = 0; matrixNum < numberOfMatrices; matrixNum++)
{
char fullFileName[256];
sprintf (fullFileName, "matrix-%02d.txt", numberOfMatrices);
matrixRows = orderedMatricesInfo[matrixNum][0][0];
matrixCols = orderedMatricesInfo[matrixNum][0][1];
int matrix[matrixRows][matrixCols];
int **matrixPointer;
matrixPointer = readMatrix(matrixRows, matrixCols, matrix, matrixNum + 1);
displayMatrix(matrixRows, matrixCols, matrixPointer);
}
}
void displayMatrix(int rows, int cols, int** matrix)
{
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
printf (" %2d", matrix[i][j]);
}
putchar ('\n');
}
putchar ('\n');
}
(note: there are a number of additional comments left in the code above, rather then detailing each suggested change in paragraph form)
Example Use/Output
$ ./bin/write_matrix
Please enter the number of rows in your matrix:
2
Please enter the number of columns in your matrix:
2
Please enter element for [0][0]:
1
Please enter element for [0][1]:
2
Please enter element for [1][0]:
3
Please enter element for [1][1]:
4
1 2
3 4
SUCCESS
Look things over and let me know if you have further questions.

C change pointer to structure

I'm not that familiar with C and try to add a row to a existing matrix structure with a function. This function will be used in a iteration loop.
In my code, I use the matrix PreparedData_B4 as reference matrix. In the first step I slice 3 rows out of PreparedData_B4 and create the matrix ActData. Afterwards I call the function add_row with the arguments mat In, mat **Out and mat Out1. Maybe there is also another idea to avoid the passing of the adress of ActData (mat **Out) and the ActData (mat Out1) itself. It was my only chance to get the right dimensions of Tmp.
EDIT: In this function, I create a temporary matrix Temp with the new dimensions. After *Out = &Tmp the new address is set and works fine in my opinion. (**Out)->n = 3, (**Out)->m = 4 and (**Out)->v[][] is accessable.
So far, so good.
After the function is completed, things go wrong. ActData->n = 0 and ActData->v[][] is not accessable.
Another questions is, how to free the memory of the "old" ActData?
#include <stdio.h>
#include <stdlib.h>
#define NELEMS(x) (int)(sizeof(x) / sizeof((x)[0]))
// Raw data
double raw_T7[][3] = {
{1800, 261.753, 1032.354},
{1750, 247.46, 1028.439},
{1700, 250.385, 1003.689},
{1243, 69.92, 816.569},
{670, 67.485, 614.319},
{533, 73.591, 533.15},
{509, 73.404, 517.456},
{485, 89.233, 515.994},
{460, 110.535, 501.412},
{435, 141.864, 471.876},
{411, 195.009, 480.623},
{386, 260.166, 529.444},
{361, 375.958, 462.411}
};
// Matrix structure
typedef struct {
int m, n;
double ** v;
} mat_t, *mat;
// Create new matrix
mat mat_new(int m, int n){
int i = 0;
mat out = malloc(sizeof(mat_t));
out->v = malloc(sizeof(double*) * m);
out->v[0] = calloc(sizeof(double), m * n);
for (i = 0; i < m; i++) out->v[i] = out->v[0] + n * i;
out->m = m;
out->n = n;
return out;
}
// Show matrix
void mat_show(mat A){
int i = 0, j = 0;
for(i = 0; i < A->m; i++) {
for (j = 0; j < A->n; j++) {
printf(" %8.3f", A->v[i][j]);
}
printf("\n");
}
printf("\n");
}
void add_row(mat In, mat **Out, mat Out1){
int i = 0, j = 0;
// Create new matrix
mat Tmp = mat_new(Out1->m + 1, Out1->n);
for (i = 0 ; i < Tmp->n ; i++) {
for(j = 0 ; j < Tmp->m ; j++){
Tmp->v[j][i] = In->v[j][i];
}
}
mat_show(Tmp);
// Delete old address
//free(Out1->v[0]);
//free(Out1->v);
//free(Out1);
*Out = &Tmp;
}
int main()
{
int i = 0, j = 0;
// Assign array address to first matrix structure
mat PreparedData_B4 = mat_new(NELEMS(raw_T7), NELEMS(raw_T7[0]));
double *ptr1[PreparedData_B4->m];
free(PreparedData_B4->v[0]);
free(PreparedData_B4->v);
PreparedData_B4->v = (double **)ptr1;
for (i = 0 ; i < PreparedData_B4->m ; i++) ptr1[i] = (double *)raw_T7 + i * NELEMS(raw_T7[0]);
// Create new matrix with the first 3 rows of PreparedData_B4
mat ActData = mat_new(3, PreparedData_B4->n);
for (i = 0 ; i < ActData->n ; i++) {
for(j = 0 ; j < ActData->m ; j++){
ActData->v[j][i] = PreparedData_B4->v[j][i];
}
}
puts("PreparedData_B4");
mat_show(PreparedData_B4);
puts("ActData");
mat_show(ActData);
puts("ActData with additional row");
add_row(PreparedData_B4, &ActData, ActData);
mat_show(ActData);
free(PreparedData_B4);
return 0;
}
SOLUTION:
Due the solid foundation of David C. Rankin and all the other responses my working example. Many thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NELEMS(x) (int)(sizeof(x) / sizeof((x)[0]))
// Raw data
double raw_T7[][3] = {
{1800, 261.753, 1032.354},
{1750, 247.46, 1028.439},
{1700, 250.385, 1003.689},
{1243, 69.92, 816.569},
{670, 67.485, 614.319},
{533, 73.591, 533.15},
{509, 73.404, 517.456},
{485, 89.233, 515.994},
{460, 110.535, 501.412},
{435, 141.864, 471.876},
{411, 195.009, 480.623},
{386, 260.166, 529.444},
{361, 375.958, 462.411}
};
// Matrix structure
typedef struct {
int m, n;
double *v;
} mat_t;
// Create new matrix
mat_t *mat_new (int m, int n)
{
mat_t *out = malloc (sizeof *out); /* allocate struct */
if (!out) {
perror ("malloc-out");
exit (EXIT_FAILURE);
}
out->v = malloc(sizeof *out->v * m * n); /* allocate for m * n doubles */
if (!out->v) {
perror ("malloc-out->v");
exit (EXIT_FAILURE);
}
out->m = m;
out->n = n;
return out;
}
// Show matrix
void mat_show(mat_t *A)
{
int i = 0, j = 0;
for(i = 0; i < A->m; i++) {
for (j = 0; j < A->n; j++)
printf(" %8.3f", (A->v)[i * A->n + j]);
putchar ('\n');
}
putchar ('\n');
}
void add_row(mat_t *In, mat_t **Out){
int i = 0, j = 0;
// Create new matrix
mat_t *Tmp = mat_new((*Out)->m + 1, (*Out)->n);
for (i = 0 ; i < Tmp->m ; i++) {
for(j = 0 ; j < Tmp->n ; j++){
(Tmp->v)[i * Tmp->n + j] = (In->v)[i * In->n + j];
}
}
// Delete old address
free((*Out)->v);
free(*Out);
// Assign new address
*Out = Tmp;
}
int main(void)
{
int rows = NELEMS(raw_T7), cols = NELEMS(raw_T7[0]);
int i = 0, j = 0;
// Assign array address to first matrix structure
mat_t *PreparedData_B4 = mat_new(rows, cols); /* allocate, set m & n */
/* copy raw_T7 to PreparedData_B4->v */
memcpy (PreparedData_B4->v, raw_T7, rows * cols * sizeof PreparedData_B4->v);
// Create new matrix with the first 3 rows of PreparedData_B4
mat_t *ActData = mat_new(3, PreparedData_B4->n);
for (i = 0 ; i < ActData->m ; i++) {
for(j = 0 ; j < ActData->n ; j++){
(ActData->v)[i * ActData->n + j] = (PreparedData_B4->v)[i * PreparedData_B4->n + j];
}
}
puts("PreparedData_B4");
mat_show(PreparedData_B4);
puts("ActData");
mat_show(ActData);
puts("ActData with additional row");
add_row(PreparedData_B4, &ActData);
mat_show(ActData);
free (PreparedData_B4->v);
free (PreparedData_B4);
return 0;
}
Before you can build the perfect house, you must build a solid foundation -- otherwise the house will not last.
You are confusing the use of pointers and allocated blocks of memory for storage of data. This is quite apparent in your mat_new() function. Think about it... You allocate for m pointers,
out->v = malloc(sizeof(double*) * m);
But then only use a single-pointer:
out->v[0] = calloc(sizeof(double), m * n);
(what are you using the other m - 1 pointers for??)
You look like you want to allocate a single block of memory to store your matrix values in, but then simulate a 2D array in your indexing (which is fine and is a very efficient approach) However, to do that, you do not use a double-pointer for v, you simply use a single-pointer (e.g. double *v;) This provides the benefit of a single-allocation and single-free for your stored data. (you still must free the struct itself)
Let's just take your mat_new (int m, int n) function and get that working properly and then output the data with your mat_show(mat_t *A) and finally free the memory we have allocated to that point, e.g.
// Create new matrix
mat_t *mat_new (int m, int n)
{
mat_t *out = malloc (sizeof *out); /* allocate struct */
if (!out) {
perror ("malloc-out");
exit (EXIT_FAILURE);
}
out->v = malloc(sizeof *out->v * m * n); /* allocate for m * n doubles */
if (!out->v) {
perror ("malloc-out->v");
exit (EXIT_FAILURE);
}
out->m = m;
out->n = n;
return out;
}
(note: I have removed the typedeffed pointer mat)
For your mat_show() function, you would then have:
// Show matrix
void mat_show(mat_t *A)
{
int i = 0, j = 0;
for(i = 0; i < A->m; i++) {
for (j = 0; j < A->n; j++)
printf(" %8.3f", (A->v)[i * A->n + j]);
putchar ('\n');
}
putchar ('\n');
}
(note: don't use printf to output a single-character, that is what putchar() is for -- though a good compiler will make that optimization for you)
If you put those functions together with a shortened example, you would have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NELEMS(x) (int)(sizeof(x) / sizeof((x)[0]))
// Raw data
double raw_T7[][3] = { {1800, 261.753, 1032.354},
{1750, 247.46, 1028.439},
{1700, 250.385, 1003.689},
{1243, 69.92, 816.569},
{670, 67.485, 614.319},
{533, 73.591, 533.15},
{509, 73.404, 517.456},
{485, 89.233, 515.994},
{460, 110.535, 501.412},
{435, 141.864, 471.876},
{411, 195.009, 480.623},
{386, 260.166, 529.444},
{361, 375.958, 462.411} };
// Matrix structure
typedef struct {
int m, n;
double *v;
} mat_t;
// Create new matrix
mat_t *mat_new (int m, int n)
{
mat_t *out = malloc (sizeof *out); /* allocate struct */
if (!out) {
perror ("malloc-out");
exit (EXIT_FAILURE);
}
out->v = malloc(sizeof *out->v * m * n); /* allocate for m * n doubles */
if (!out->v) {
perror ("malloc-out->v");
exit (EXIT_FAILURE);
}
out->m = m;
out->n = n;
return out;
}
// Show matrix
void mat_show(mat_t *A)
{
int i = 0, j = 0;
for(i = 0; i < A->m; i++) {
for (j = 0; j < A->n; j++)
printf(" %8.3f", (A->v)[i * A->n + j]);
putchar ('\n');
}
putchar ('\n');
}
int main (void)
{
int rows = NELEMS(raw_T7), cols = NELEMS(raw_T7[0]);
mat_t *PreparedData_B4 = mat_new(rows, cols); /* allocate, set m & n */
/* copy raw_T7 to PreparedData_B4->v */
memcpy (PreparedData_B4->v, raw_T7, rows * cols * sizeof PreparedData_B4->v);
mat_show (PreparedData_B4); /* output matrix */
free (PreparedData_B4->v);
free (PreparedData_B4);
}
(note: string.h was included to make the memcpy() function available to initialize out->v from raw_T7 in a single call )
Example Use/Output
$ ./bin/mat_prepare
1800.000 261.753 1032.354
1750.000 247.460 1028.439
1700.000 250.385 1003.689
1243.000 69.920 816.569
670.000 67.485 614.319
533.000 73.591 533.150
509.000 73.404 517.456
485.000 89.233 515.994
460.000 110.535 501.412
435.000 141.864 471.876
411.000 195.009 480.623
386.000 260.166 529.444
361.000 375.958 462.411
Memory Use/Error Check
$ valgrind ./bin/mat_prepare
==10301== Memcheck, a memory error detector
==10301== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10301== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==10301== Command: ./bin/mat_prepare
==10301==
1800.000 261.753 1032.354
1750.000 247.460 1028.439
1700.000 250.385 1003.689
1243.000 69.920 816.569
670.000 67.485 614.319
533.000 73.591 533.150
509.000 73.404 517.456
485.000 89.233 515.994
460.000 110.535 501.412
435.000 141.864 471.876
411.000 195.009 480.623
386.000 260.166 529.444
361.000 375.958 462.411
==10301==
==10301== HEAP SUMMARY:
==10301== in use at exit: 0 bytes in 0 blocks
==10301== total heap usage: 3 allocs, 3 frees, 1,352 bytes allocated
==10301==
==10301== All heap blocks were freed -- no leaks are possible
==10301==
==10301== For counts of detected and suppressed errors, rerun with: -v
==10301== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
This is what it appears you were trying to accomplish. Let me know if I misinterpreted your intent or if you have further questions. Get your memory use correct first to provide a solid foundation and build from there.

matrix operations reading input from file

I'd like to perform matrix operations like A*B+C. The matrix are read from a file thus formatted:
1 3 4 5
0 1 0 6
0 0 1 7
2 7 0 1
*
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
*
1 2
3 4
I can already read the matrices and the operators, I don't know how to perform the operations. Suppose that you have: AB+C so you must perfom firstly (AB) then I think the best strategy is that this result becomes B and ultimately perform B+C. I'm not sure on how to reallocate B and perform the operations in the correct order. To keep it simple I'm just considering multiplication for the moment.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MINA 2 /* if you need a constant, #define one (or more) */
#define MAXC 1024
struct m{
int **data;
size_t row, col;
};
void multiply(struct m *A, struct m *B)
{
int i, j, k;
struct m C;
C.data = malloc(sizeof(int) * A->row);
C.row = A->row;
C.col = B->col;
/*initialize C to 0*/
for ( j = 0; j < C.row; j++) /* for each row */
for ( k = 0; k < C.col; k++) /* for each col */
C.data[j][k] = 0; /* output int */
// Multiplying matrix A and B and storing in C.
for(i = 0; i < A->row; ++i)
for(j = 0; j < B->col; ++j)
for(k=0; k < A->col; ++k)
C.data[i][j] += A->data[i][k] * B->data[k][j];
//free(B->data);
*B = C;
}
void print_matrix(struct m *matrix)
{
int j, k;
for ( j = 0; j < matrix->row; j++) { /* for each row */
for ( k = 0; k < matrix->col; k++) /* for each col */
printf ("%4d", matrix->data[j][k]); /* output int */
putchar ('\n'); /* tidy up with '\n' */
free (matrix->data[j]); /* free row */
}
free (matrix->data); /* free pointers */
}
int main (int argc, char **argv)
{
struct m *matrix; /* pointer to array type */
size_t aidx = 0, maxa = MINA, /* matrix index, max no. allocated */
nrow = 0, ncol = 0, /* current row/col count */
maxrow = MINA, nop = 0; /* alloc'ed rows current array, no. op */
char buf[MAXC], /* buffer to hold each line */
op[MAXC]; /* array to hold operators */
int i;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
/* allocate/validate maxa no. of matrix */
if (!(matrix = calloc (maxa, sizeof *matrix))) {
perror ("calloc-matrix");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
int off = 0, n; /* offset from start of line, n for "%n" */
size_t tidx = 0; /* temporary array index */
char *p = buf; /* pointer to advance in sscanf */
int tmp[MAXC / 2 + 1]; /* temporary array, sized for max no. ints */
if (!isdigit(*buf)) { /* if 1st char non-digit, end of array */
op[nop++] = *buf; /* store operator */
if (nrow) /* if rows stored */
matrix[aidx++].row = nrow; /* set final number of rows */
nrow = ncol = 0; /* reset nrow/ncol counters */
maxrow = MINA; /* reset allocate rows */
continue; /* get next line of data */
}
if (aidx == maxa) { /* check if no. of structs need realloc */
void *atmp = realloc (matrix, 2 * maxa * sizeof *matrix); /* realloc */
if (!atmp) { /* validate */
perror ("realloc-matrix");
return 1;
}
matrix = atmp; /* assign new block to matrix */
/* set all new bytes zero (realloc doesn't initialize) */
memset (matrix + maxa, 0, maxa * sizeof *matrix);
maxa *= 2; /* update struct count */
}
/* read all integers in line into tmp array */
while (sscanf (p + off, "%d%n", &tmp[tidx], &n) == 1) {
off += n;
tidx++;
}
if (tidx) { /* if integers stored in tmp */
if (nrow == 0) { /* if first row in array */
/* allocate/validate maxrow pointers */
if (!(matrix[aidx].data = malloc (maxrow * sizeof *matrix[aidx].data))) {
perror ("malloc-matrix[aidx].data");
return 1;
}
matrix[aidx].col = tidx; /* fix no. cols on 1st row */
}
else if (nrow == maxrow) { /* realloc of row ptrs req'd? */
/* always realloc with temp ptr */
void *atmp = realloc (matrix[aidx].data, 2 * maxrow * sizeof *matrix[aidx].data);
if (!atmp) { /* validate every alloc/realloc */
perror ("realloc-matrix[aidx].data");
return 1;
}
matrix[aidx].data = atmp; /* assign realloced block to ptr */
maxrow *= 2; /* update maxrow to current alloc */
}
if (tidx != matrix[aidx].col) { /* validate no. of columns */
fprintf (stderr, "error: invalid number of columns " "matrix[%zu].data[%zu]\n", aidx, nrow);
return 1;
}
if (!(matrix[aidx].data[nrow] = /* allocate storagre for integers */
malloc (tidx * sizeof *matrix[aidx].data[nrow]))) {
perror ("malloc-matrix[aidx].data[nrow]");
return 1;
}
/* copy integers from tmp to row, increment row count */
memcpy (matrix[aidx].data[nrow++], tmp, tidx * sizeof *tmp);
}
} /*end of while (fgets (buf, MAXC, fp)) */
if (nrow) /* handle final array */
matrix[aidx++].row = nrow; /* set final number of rows */
if (fp != stdin) fclose (fp); /* close file if not stdin */
/*Printing the file */
for(i=0; i<aidx; i++){
print_matrix(&matrix[i]);
printf("%c\n",op[i]);
}
printf("=\n");
for(i=0; i<aidx; i++){
if(op[i] =='*')
multiply(&matrix[aidx],&matrix[aidx+1]);
}
print_matrix(&matrix[aidx-1]); /*Print the result */
free (matrix); /* free structs */
return 0;
}
My original answer is still correct in its content, I will leave it quoted at the end. Now the problem is more clear. A "naive" algorithm to solve this problem could be to, if you only have multiplications or sums, read the file and keep a list where you put:
If you have a * sign, multiply the operands, saving only the result
If you have a + sign, go to the next item
When you are done sum all the items in the list. In pseudocode:
list = []
i = 0
op = +
for item in file {
if item is operator {
op = item
if op == + {
i++
}
} else if item is matrix {
if len(list) > i {
list[i] = list[i] op item
} else {
list[i] = item //auto append if i < len(list)
}
}
}
result = list[0]
for item in list[1:] {
result += item
}
Keep in mind this:
Is pseudo code
By all mean not the best way to do it I think
If I understood correctly the question you want to know: Where should you put the result of the operation and how to decide in which order should you do the operations. So, firstly: Your idea that, when doing AB+C you should put the result of AB in B is not bad, but, before doing something like this you should know that B is no longer used in the rest of the equation. Consider AB+B, now if you overwrite B, you lost it and are unable to complete the equation. You need a graph of relations of variables to do that operation, if you have it you can not only overwrite an unused variable with a result of an operation (usually free the old variable if now unused and allocate a new one) but also reuse the result of an operation later, for instance if you have to do ABC + AB, you can see that there is no point in re-calculating AB. The second question similarly requires you to build an operation tree, I suggest to you to do so using a LL(1) parser.

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)

using realloc with a for loop

I am using realloc to allocated memory at runtime in dynamic array. Firstly, I allocated a memory with calloc with sizeof a random integer a. In my program, I have taken a=2. After that I want to store some 14 random values generated, so I have to resize the memory using realloc. I am doing the same in a for loop. FOr 1 iteration, realloc works but after that size doesnt increase and a error occurs "corruption in heap". I am not able to understand the problem. Pls help me if you can, in understanding where the problem is occuring and how to solve it.
Thanks a lot.
Below is my code:
j=j*a; //a=3
numbers = (int*) calloc(b, j); //b=14, no of elements I want to store
printf("Address:%p\n",numbers);
if (numbers == NULL)
{
printf("No Memory Allocated\n");
}
else
{
printf("Initial array size: %d elements\n", a);
printf("Adding %d elements\n", b);
}
srand( (unsigned) time( NULL ) );
for(count = 1; count <= b ; count++)
{
if(i <= j)
{
numbers[count] = rand() % 100 + 1;
printf( "Adding Value:%3d Address%p\n", numbers[count],numbers[count] );
i++;
}
if (i > j)
{
printf("Increasing array size from %d bytes to %d bytes\n",j,j*a);
j=j*a;
numbers = (int*) realloc(numbers,j);
printf("Address:%p\n",numbers);
if(numbers == NULL)
{
printf("No Memory allocated\n");
}
}
}
free(numbers);
return 0;
}
The initial array length (length and size are not the same) is b, not a.
Adding b elements? I don't think you are.
Arrays are zero-based in C. You loop should be for(count=0; count<b ; count++).
count is a terrible name for a loop variable. count should hold the number of elements and not be a loop variable.
It's hard to imagine what j could be. Since you use it as the element size in your call to calloc it ought be at least be a multiple of 4, the size of in int. What is it?!
The realloc doesn't seem to bear any relation to the calloc.
I'm sure there are lots of other problems. If you want more help then a clear statement of what your goal is would be required.
EDIT
It sounds like you want something like this:
int capacity = 10;
int count = 40;
int i;
int* array = (int*)malloc(capacity*sizeof(int));
for (i=0; i<count; i++)
{
if (i==capacity)
{
capacity *= 2;
array = (int*)realloc(array, capacity*sizeof(int));
}
array[i] = RandomIntInRange(1, 100);
}
free(array);
Notes:
No error checking. In production code you would check that the allocations succeeded, and the realloc done this way would leak if it failed. But there's no point confusing the message with error checking when you are still at this level of understanding.
No reading input - you can do that.
No writing output - you can do that.
The integer "j" is not initialized in your code, resulting in a = 0 * 3, meaning a will be zero and no memory will be allocated. The segfault is due to you not handling that numbers is NULL. Change to and set j to something meaningful
#include <stdlib.h>
#include <stdio.h>
void
main (int argc, char *argv[])
{
int a = 3;
int j = 1 * a; //a=3
int b = 14;
int *numbers = calloc (b, j); //b=14, no of elements I want to store
int count = 0, i = 0;
printf ("Address:%p\n", numbers);
if (numbers == NULL)
{
printf ("No Memory Allocated\n");
return;
}
else
{
printf ("Initial array size: %d elements\n", a);
printf ("Adding %d elements\n", b);
}
srand ((unsigned) time (NULL));
for (count = 1; count <= b; count++)
{
if (i <= j)
{
numbers[count] = rand () % 100 + 1;
printf ("Adding Value:%3d Address%p\n", numbers[count],
&(numbers[count]));
i++;
}
if (i > j)
{
printf ("Increasing array size from %d bytes to %d bytes\n", j,
j * a);
j = j * a;
numbers = (int *) realloc (numbers, j);
printf ("Address:%p\n", numbers);
if (numbers == NULL)
{
printf ("No Memory allocated\n");
}
}
}
free (numbers);
}

Resources