2D array as contiguous block of memory - c

I know this question was answered but it somehow doesn't work for me.
I dynamically allocate memory for array like this:
arr = (int**)(malloc(rows*sizeof(int*)));
arr[0] = (int*)(malloc(rows*columns*sizeof(int))); // <-- THIS DOESN'T WORK
printf("\nArray: \n");
while(fscanf(fp, "%d", &num) == 1) {
//arr[row] = (int*)(malloc(columns*sizeof(int))); <---THIS WORKS
arr[row][col] = num;
printf("%d ", arr[row][col]);
if((++col == columns)){
row++;
col = 0;
printf("\n");
}
}
It throws segmentation fault after 4th row, if matrix is 6x6.
Any advice? Thanks
EDIT:
See: http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/ point number 4. If I do it like in point 3, it works. But I need it like in 4.

There exists no case where you should use fragmented malloc calls like you do. It is wide-spread but bad and incorrect practice. As you point out, it will not give you a true 2D array in adjacent memory, but rather a fragmented, slow mess.
How to do this properly:
In standard C, write
int (*arr)[rows][columns] = malloc (sizeof(*arr));
(*arr)[r][c] = something;
...
free(arr);
or if you prefer to use syntax which is easier-to-read (but perhaps harder to understand):
int (*arr)[columns] = malloc (sizeof(int[rows][columns]));
arr[r][c] = something;
...
free(arr);
In obsolete versions of C, you will have to write a "mangled array":
int* arr = malloc(rows * columns * sizeof(*arr));
arr[r*c] = something;
...
free(arr);

To allocate a contiguous memory, you'll have to use
arr = malloc(sizeof(int *) * rows);
arrayData = malloc(sizeof(int) * columns * rows);
for(i = 0; i < rows; i++)
arr[i] = arrayData + i * columns ;
To deallocate you'll need to have
free( arrData );
free( arr );
See here

You need to allocate memory for each row, not just the first row. Replace
arr[0] = (int*)(malloc(rows*columns*sizeof(int)));
with
for(int i = 0; i < rows; i++)
arr[i] = malloc(columns * sizeof(int));
The changes made here are:
All the rows will be allocated columns * sizeof(int) bytes of memory.
Casting the result of malloc is pointless in C. I've removed it.
You might need to add a check in the loop to prevent an overflow. Something like
if(row == rows)
{
puts("Matrix full; Exiting loop...");
break;
}
The fixed code would be
int i, row = 0, col = 0;
int rows = 6, columns = 6; /* For 6x6 matrix */
arr = malloc(rows * sizeof(int*));
for(i = 0; i < rows; i++)
arr[i] = malloc(columns * sizeof(int));
printf("\nArray: \n");
while(fscanf(fp, "%d", &num) == 1) {
arr[row][col] = num;
printf("%d ", arr[row][col]);
if(++col == columns){
row++;
col = 0;
printf("\n");
}
if(row == rows)
{
puts("Matrix full; Exiting loop...");
break;
}
}

For a 6x6 matrix, dynamic memory is overkill. You should simply use:
int arr[rows][cols];
This is much simpler, cleaner, quicker, less error prone and generally all round safer — as long as you keep the matrix size small enough that it easily fits on the stack. If you need a large matrix (say from 1 MiB upwards, but you'll need to tune your threshold to suit your systems), then dynamic memory is relevant.
You can make the single allocation to arr[0] work, but you have to do explicit assignments to each of arr[1] through arr[5]. I did it this way:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int rows = 6;
int cols = 6;
int **arr = (int**)(malloc(rows*sizeof(int*)));
arr[0] = (int*)(malloc(rows*cols*sizeof(int)));
for (int i = 1; i < rows; i++)
arr[i] = arr[i-1] + cols;
printf("\nArray: \n");
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
arr[i][j] = (i+1) * (cols + 1 - j);
}
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("%3d", arr[i][j]);
putchar('\n');
}
free(arr[0]);
free(arr);
return(0);
}
Sample output:
Array:
7 6 5 4 3 2
14 12 10 8 6 4
21 18 15 12 9 6
28 24 20 16 12 8
35 30 25 20 15 10
42 36 30 24 18 12
Running valgrind gives a clean bill of health.

Related

Swap sub-arrays of a multi-dimensional array in C

I have a 50 x 50 matrix arr[50][50] and need to swap the values in the sub-array arr[0] and arr[1].
ie, the whole 50 elements in each sub-array need to be swapped.
The only way I can think of to do this is by using a loop like:
for(i=0; i<50; ++i)
{
int t = arr[0][i];
arr[0][i] = arr[1][i];
arr[1][i] = t;
}
I was wondering if there were any simpler or shorter methods? Using pointers maybe?
I tried things like
int *t = arr[0];
arr[0] = arr[1];
arr[1] = t;
but it gave error at the first line about "incompatible types when assigning to type 'int[2]' from type 'int *' ".
Then I tried pointer to an array
int (*t)[50] = arr[0];
arr[0] = arr[1];
arr[1] = t;
This time I got error at the second line about "incompatible types when assigning to type 'int[50]' from type 'int *' ".
If your matrix is implemented as arr[50][50] then the only way to physically swap two rows is to physically exchange data in memory. Your cycle is one way to do it. The rest would be just variations of that approach. You can swap matrix elements one-by-one (your cycle), you can swap the entire rows using an intermediate row-sized buffer (memcpy approach). All of them still do the same thing. There's no way around it.
If your array were implemented differently - say, a "jagged" array implemented as array of pointers to sub-arrays, then you would be able to just swap two pointers and be done with it. But in case of arr[50][50] it is not possible.
If you wish, you can just "convert" your current array into a "jagged" version by a separate row-pointer array. That row-pointer array will now become your matrix a, while the original a[50][50] will become a_data
int a_data[50][50];
int *a[50];
for (unsigned i = 0; i < 50; ++i)
a[i] = a_data[i];
/* Fill the matrix */
for (unsigned i = 0; i < 50; ++i)
for (unsigned j = 0; j < 50; ++j)
a[i][j] = rand();
/* Print the matrix */
for (unsigned i = 0; i < 50; ++i)
{
for (unsigned j = 0; j < 50; ++j)
printf("%d ", a[i][j]);
printf("\n");
}
/* Swap the rows */
int *temp = a[0];
a[0] = a[1];
a[1] = temp;
/* Print the matrix */
for (unsigned i = 0; i < 50; ++i)
{
for (unsigned j = 0; j < 50; ++j)
printf("%d ", a[i][j]);
printf("\n");
}
Note, that despite the physical structure of a is now different, you can still use a[i][j] syntax to work with it.
As explained in the comments, and within the other answers, in order to swap rows of an actual 2D array (as apposed to an array of pointers), you must copy/move the data from the source to target row in memory. The most straight forward way to approach this is either with a loop to copy element-by-element to temporary storage to effect the swap, or use the memory copy functions provided by the C-library (e.g. memcpy or memmove). A simple implementation using memcopy (shown with a 3x10 array for array for purposes of the example) would be:
#include <stdio.h>
#include <string.h>
enum { ROW = 3, COL = 10 };
void swaprow (int (*a)[COL], int c1, int c2);
void prna (int (*a)[COL]);
int main (void) {
int a[ROW][COL] = {{0}};
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
a[i][j] = i;
prna (a);
swaprow (a, 0, 1);
putchar ('\n');
prna (a);
return 0;
}
void swaprow (int (*a)[COL], int c1, int c2)
{
int tmp[COL];
memcpy (tmp, a[c1], COL * sizeof *tmp);
memcpy (a[c1], a[c2], COL * sizeof *a[c1]);
memcpy (a[c2], tmp, COL * sizeof *a[c2]);
}
void prna (int (*a)[COL])
{
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++)
printf ("%2d", a[i][j]);
putchar ('\n');
}
}
Example Use/Output
$ ./bin/array2d_swap_row
0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2
1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0
2 2 2 2 2 2 2 2 2 2
Look things over and let me know if you have any questions.
You will have to copy the data to be swapped with memcpy, I have provided sample to program to show how you can do it(ie swap arr[0] and arr[1]).
int main(void) {
// your code goes here
int t[3];
int arr[3][3]={{1,2,3},{4,5,6},{7,8,9}};
printf("\n%d %d %d",arr[0][0],arr[0][1],arr[0][2]);
printf("\n%d %d %d",arr[1][0],arr[1][1],arr[1][2]);
memcpy(t,arr[0],sizeof(t));
memcpy(arr[0],arr[1],sizeof(t));
memcpy(arr[1],t,sizeof(t));
printf("\n%d %d %d",arr[0][0],arr[0][1],arr[0][2]);
printf("\n%d %d %d",arr[1][0],arr[1][1],arr[1][2]);
return 0;
}

I am getting a run time error for the following code

#include<stdio.h>
#include<stdlib.h>
int main() {
int i, j, a[10], result = 0,p;
int *m = malloc(sizeof(int)*8);
for(i = 0; i < 10; i++){
scanf("%d", &a[i]);
result += a[i];
}
//printf("%d\n", result);
//printf("\n");
//for(i = 0; i < 8; i++) {
for(j = 0; j < 9; j++) {
scanf("%d", &m[j]);
result = result - m[j];
p = result / 2;
}
return p;
}
In this code I am getting a runtime error. Any help would be appreciated. Thanks!
Insufficient memory allocated.
int *m=malloc(sizeof(int)*8); // 8 `int`
...
for(j=0;j<9;j++){
scanf("%d",&m[j]); // attempt to set the the 9th `int`, m[8]
Allocate sufficient memory.
#define JSIZE 9
int *m=malloc(sizeof *m * JSIZE);
if (m == NULL) Handle_OutOfMemory();
...
for(j=0;j<JSIZE;j++){
if (scanf("%d",&m[j]) != 1) Handle_BadInput();
Firstly, you can typecast the malloc allocated space to (int *) as by default malloc allocates space as (void *).
SEcondly, you are running the loop j=0 to 8 i.e 9 times however u have allocated space for just 8.Hence you have a kindof array index out of bounds error

C - Read matrix of unknown size from file

I have file that has 30 matrices and each matrix has unknown size of rows and columns(with a max size of 1000). For instance:
0 5 2
5 0 2
1 6 0
0 9 7 4
3 0 9 1
9 1 0 4
9 4 1 0
I need to read each matrix into a 2d array. What would be the most efficient way of doing this?
This is what I have so far:
int** mat=malloc(1000000*sizeof(int*));
for(i=0;i<1000000;++i)
mat[i]=malloc(4*sizeof(int));
while(!feof(file))
{
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++){
fscanf(file,"%d%*[^\n]%*c",&mat[i][j]);
printf("%d\n", mat[i][j]);
}
}
}
Well the most efficient way is definitely not that. First figure out how big an array you need, then allocate it.
Apparently some matrices are small, so there is no need to allocate the maximum size 1000x1000. One way is to put the matrix in a structure to make it easier to keep track of size:
struct s_matrix
{
int **matrix;
int N; //one side of the square matrix N x N
};
typedef struct s_matrix Matrix;
Then allocate and free the matrix
void allocate_matrix(Matrix *m, int N)
{
m->N = N;
m->matrix = (int**)malloc(N * sizeof(int*));
*m->matrix = (int*)malloc(N * N * sizeof(int));
for (int i = 0; i < N; i++)
m->matrix[i] = *m->matrix + i * N;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
m->matrix[i][j] = 0;
}
void free_matrix(Matrix *m)
{
if (!m) return;
if (!m->matrix) return;
free(*m->matrix);
free(m->matrix);
}
Now we can declare how many matrices we need. It looks like this number is fixed at 30, so I don't think we need dynamic allocation.
int main()
{
const int max_count = 30;
Matrix list[max_count];
for (int i = 0; i < max_count; i++)
list[i].matrix = NULL;
allocate_matrix(&list[0], 3);//allocate 3x3 matrix
allocate_matrix(&list[1], 1000);//1000x1000
allocate_matrix(&list[2], 4000);//4000x4000
int **m;
m = list[0].matrix;
m[0][0] = 0;
m[0][1] = 1;
m[0][2] = 2;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
printf("%02d %s", m[i][j], (j == 2) ? "\n" : "");
//...
for (int i = 0; i < max_count; i++)
free_matrix(&list[i]);
printf("hey it worked, or maybe it didn't, or it did but there is memory leak\n");
return 0;
}

How to efficiently store a triangular matrix in memory?

I want to store a lower triangular matrix in memory, without storing all the zeros.
The way I have implemented it is by allocating space for i + 1 elements on the ith row.
However, I am new to dynamic memory allocation in C and something seems to be wrong with my first allocation.
int main ()
{
int i, j;
int **mat1;
int dim;
scanf("%d", &dim);
*mat1 = (int**) calloc(dim, sizeof(int*));
for(i = 0; i < dim; i++)
mat1[i] = (int*) calloc(i + 1, sizeof(int));
for(i = 0; i < dim; i++)
{
for(j = 0; j < i + 1; j++)
{
scanf("%d", &mat1[i][j]);
}
}
/* Print the matrix without the zeros*/
for(i = 0; i < dim; i++)
{
for(j = 0; j < (i + 1); j++)
{
printf("%d%c", mat1[i][j], j != (dim-1) ? ' ' : '\n');
}
}
return 0;
}
If you want to conserve space and the overhead of allocating every row of the matrix, you could implement a triangular matrix by using clever indexing of a single array.
A lower triangular matrix (including diagonals) has the following properties:
Dimension Matrix Elements/row Total elements
1 x . . . 1 1
2 x x . . 2 3
3 x x x . 3 6
4 x x x x 4 10
...
The total number of elements for a given dimension is:
size(d) = 1 + 2 + 3 + ... + d = (d+1)(d/2)
If you lay the rows out consecutively in a single array, you can use the formula above to calculate the offset of a given row and column (both zero-based) inside the matrix:
index(r,c) = size(r-1) + c
The formulas above are for the lower triangular matrix. You can access the upper matrix as if it was a lower matrix by simply reversing the indexes:
index((d-1)-r, (d-1)-c)
If you have concerns about changing the orientation of the array, you can devise a different offset calculation for the upper array, such as:
uindex(r,c) = size(d)-size(d-r) + c-r
Sample code:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define TRM_SIZE(dim) (((dim)*(dim+1))/2)
#define TRM_OFFSET(r,c) (TRM_SIZE((r)-1)+(c))
#define TRM_INDEX(m,r,c) ((r)<(c) ? 0 : (m)[TRM_OFFSET((r),(c))])
#define TRM_UINDEX(m,r,c,d) ((r)>(c)?0:(m)[TRM_SIZE(d)-TRM_SIZE((d)-(r))+(c)-(r)])
#define UMACRO 0
int main (void)
{
int i, j, k, dimension;
int *ml, *mu, *mr;
printf ("Enter dimension: ");
if (!scanf ("%2d", &dimension)) {
return 1;
}
ml = calloc (TRM_SIZE(dimension), sizeof *ml);
mu = calloc (TRM_SIZE(dimension), sizeof *mu);
mr = calloc (dimension*dimension, sizeof *mr);
if (!ml || !mu || !mr) {
free (ml);
free (mu);
free (mr);
return 2;
}
/* Initialization */
srand (time (0));
for (i = 0; i < TRM_SIZE(dimension); i++) {
ml[i] = 100.0*rand() / RAND_MAX;
mu[i] = 100.0*rand() / RAND_MAX;
}
/* Multiplication */
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
for (k = 0; k < dimension; k++) {
mr[i*dimension + j] +=
#if UMACRO
TRM_INDEX(ml, i, k) *
TRM_UINDEX(mu, k, j, dimension);
#else
TRM_INDEX(ml, i, k) *
TRM_INDEX(mu, dimension-1-k, dimension-1-j);
#endif
}
}
}
/* Output */
puts ("Lower array");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
printf (" %2d", TRM_INDEX(ml, i, j));
}
putchar ('\n');
}
puts ("Upper array");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
#if UMACRO
printf (" %2d", TRM_UINDEX(mu, i, j, dimension));
#else
printf (" %2d", TRM_INDEX(mu, dimension-1-i, dimension-1-j));
#endif
}
putchar ('\n');
}
puts ("Result");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
printf (" %5d", mr[i*dimension + j]);
}
putchar ('\n');
}
free (mu);
free (ml);
free (mr);
return 0;
}
Note that this is a trivial example. You could extend it to wrap the matrix pointer inside a structure that also stores the type of the matrix (upper or lower triangular, or square) and the dimensions, and write access functions that operate appropriately depending on the type of matrix.
For any non-trivial use of matrices, you should probably use a third-party library that specializes in matrices.
mat1 = calloc(dim,sizeof(int*));
mat1 is a double pointer.You need to allocate memory for your array of pointers and later you need to allocate memory to each of your pointers individually.No need to cast calloc()
You are dereferencing mat1 at line 8 before it has even been set to point anywhere. You are allocating an array of pointers to int, but you are not assigning that to mat1 but to the dereference of mat1, which is uninitialized, we don't know what it points to.
So this line:
// ERROR: You are saying an unknown memory location should have the value of calloc.
*mat1 = (int**)calloc(dim,sizeof(int*));
Should change to:
// OK: Now you are assigning the allocation to the pointer variable.
mat1 = (int**)calloc(dim,sizeof(int*));

Using pointers instead of an array [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I wrote this program a few weeks ago using arrays and now I need to use pointers instead of using arrays. I'm not exactly sure how to go about doing that so any tips would be appreciated! Thanks! :D
Here is the code:
#include <stdio.h>
int showArray(int row);
int exchangeRow(int row1, int row2);
int x, y;
int array[10][10];
int j;
int k;
int inputrow;
int inputcolumn;
int scanrow;
int temp;
int row1;
int row2;
int main() {
// Initialize array
for(j = 0; j < 10; j++) {
printf("\n");
for(k = 0; k < 10; k++) {
array[j][k] = j * 10 + k;
printf("%d ", array[j][k]);
}
}
printf("\n \n");
// Print out selected row
printf("Type in a number for the corresponding row to be printed \n");
scanf("%d", &inputrow);
if(inputrow >= 0 && inputrow < 10) {
for(j = 0; j < 10; j++) {
printf("%d ", array[inputrow][j]);
}
}
printf("\n \n");
//Print out selected column
printf("Type in a number for the corresponding column to be printed \n");
scanf("%d", &inputcolumn);
if(inputcolumn >= 0 && inputcolumn < 10) {
for(j = 0; j < 10; j++) {
printf("%d ", array[j][inputcolumn]);
}
}
printf("\n \n");
printf("Type in a number for the row that method showArray will print \n");
scanf("%d", &scanrow);
showArray(scanrow);
printf("\n \n");
printf("Type in two numbers for the rows that method exchangeRow will switch \n");
scanf("%d %d", &row1, &row2);
exchangeRow(row1, row2);
printf("\n \n");
system("PAUSE");
}
int showArray(int row) {
for(j = 0; j < 10; j++) {
printf("%d ", array[row][j]);
}
}
int exchangeRow(int row1, int row2) {
if(row1 >= 0 && row1 < 10 && row2 >= 0 && row2 < 10) {
temp = row1;
row1 = row2;
row2 = temp;
printf("The first row now holds the values: ");
showArray(row1);
printf("\n");
printf("The second row now holds the values: ");
showArray(row2);
}
}
I take it you mean "using dynamic memory allocation"...
The way a lot of people do 2D arrays dynamically is like this:
const size_t nrows = 10, ncols = 10;
int **array = malloc( nrows * sizeof(int*) );
for( i = 0; i < nrows; i++ ) {
array[i] = malloc( ncols * sizeof(int) );
}
But I hate this. If you are doing production code, this can be very slow. It's also harder to handle the case where you run out of memory, and there's no guaranteed locality of your array. Plus, it's ugly to free:
for( i = 0; i < nrows; i++ ) free(array[i]);
free(array);
In memory, your static array[10][10] is one contiguous block. So you should do the same:
int **array = malloc( nrows * sizeof(int*) );
array[0] = malloc( nrows * ncols * sizeof(int) );
for( i = 1; i < nrows; i++ ) {
array[i] = array[i-1] + ncols;
}
To free that:
free(array[0]);
free(array);
I often take this a step further, and do a single memory allocation instead of two. That way I have just one pointer. But I won't do that here. You have to be a little conscious of alignment, and the code is a little messier. It's an optimization that usually you don't need.
Hope that helps.
To be more specific, what is required of you is to use pointer notation instead of array notaiton
This would probably mean that your 2 dimensional array should be allocated as an array of pointers. Also it's individual elements should be accessed using pointers rather than the usual array indexing.
For e.g.
int * a = malloc(10 * sizeof(int)); // allocate memory for 10 integers
*a = 1; // assign first element of array
*(a+1) = 2; // assign second
The above was for 1D array. Extend it to multiple dimensions as in your original program.
When you declare an array, such as int arr[4];, arr actually "points" to a location in memory with 4 "spaces" that holds an integer each.
&arr means "address of" arr.
So, a pointer to arr could be defined as:
int *ptr = &arr[0];
But how would you get the data that ptr points to? The answer is:
*ptr;
But, this will only show you the first value of the data stored in the first "space" that arr occupies. To get the others in the array, all you need to do is increment your pointer along the space in memory, like so:
ptr++;
Further information can be found here: http://alumni.cs.ucr.edu/~pdiloren/C++_Pointers/neighbor.htm

Resources