I'm sort of confused between these 2 declarations
int *a;
int (*a)[3]
As I understand it, both of these give us a single pointer pointing to nothing in memory. The 2nd one is shown to be an example of a pointer pointing to an array of 3 ints in memory. But since this memory has not even been allocated, does it make any sense.
To make the pointer point to an array of 3 ints in memory, we need to do a a = (int*)malloc(sizeof(int) * 3). Doing this for the first one AND the second one will both give me a pointer pointing to a memory location where 12 consecutive bytes store my 3 numbers.
So why use int (*a)[3] at all if eventually I have to use malloc ?
So why use int (*a)[3] at all if eventually I have to use malloc ?
It is very useful for variable length arrays when you want to create a real 2d array using dynamic memory:
#include <stdio.h>
#include <stdlib.h>
void *fn_alloc(int rows, int cols)
{
int (*arr)[cols];
int i, j;
arr = malloc(sizeof(int [rows][cols]));
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
arr[i][j] = (i * cols) + j;
}
}
return arr;
}
void fn_print(int rows, int cols, int (*arr)[cols])
{
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
printf("\t%d", arr[i][j]);
}
printf("\n");
}
}
int main(void)
{
int rows, cols;
scanf("%d %d", &rows, &cols);
int (*arr)[cols] = fn_alloc(rows, cols);
fn_print(rows, cols, arr);
free(arr);
return 0;
}
In other words, when dynamic memory is involved, your first declaration is useful for pointing to an array of n dimensions while the second one is useful to point to an array of array of n dimensions.
So why use int (*a)[3] at all if eventually I have to use malloc ?
Because in most such cases (dynamically sized 2D matrixes), you should have some abstract data type using flexible array members. This answer is very relevant to your question (which is a near duplicate).
Related
I'm trying to generate a matrix of some arbitrary dimensions. I can do it just fine by calling scanf in main and then assigning matrix elements on a row by row basis, but trying to do it in a single function, outside of main, (and only if scanf() is called outside of main) gives me a segfault error:
int **genmat(int nrow, int ncol){
int i,j;
int **mat = (int**) malloc(sizeof(int)*ncol*nrow);
char rowbuff[16];
for(i=0; i < nrow; i++){
INPUT: scanf("%[^\n]%*c",rowbuff);
if(strlen(rowbuff) != ncol){
printf("Error: Input must be string of length %d\n", ncol);
goto INPUT;
}
else{
for(j=0; j < ncol; j++){
if(rowbuff[j] == '1'){
mat[i][j] = 1;
}
else{
mat[i][j] = 0;
}
}
}
}
return(mat);
}
The following works just fine:
int *genrow(int ncol, char *rowbuff){
int i;
int *row = malloc(sizeof(int)*ncol);
for(i=0;i<ncol;i++){
row[i] = rowbuff[i]%2;
}
return(row);
}
with the following in my main function to call genrow() for each row of the matrix:
for(i=0; i < row; i++){
INPUT: scanf("%[^\n]%*c",rowbuff);
if(strlen(rowbuff) != col){
printf("Error: Input must be string of length %d\n", col);
goto INPUT;
}
else{
int *newrow = genrow(col, rowbuff);
for(j=0; j < col; j++){
matrix[i][j] = newrow[j];
}
free(newrow);
newrow = NULL;
}
}
Why is the behavior different in these two contexts?
Dynamically allocated 2D arrays are unfortunately burdensome and ugly in C. To properly allocate one, it is very important that you do so with a single call to malloc, just as you tried to do. Otherwise it won't be a 2D array, but instead some segmented, slow look-up table.
However, the result of that malloc call will be a pointer to a 2D array, not a pointer-to-pointer. In fact, pointer-pointers have nothing to do with 2D arrays whatsoever - this is a widespread but incorrect belief.
What you should have done is this:
int (*mat)[nrow][ncol] = malloc( sizeof(int[nrow][ncol] );
This is an array pointer to a 2D array. This syntax is already a bit burdensome, but to make things worse, it is not easy to pass this array pointer back to main, because it is a local pointer variable. So you would need to use a pointer to an array pointer... and there's no pretty way to do that. It goes like this:
void genmat (size_t nrow, size_t ncol, int (**mat)[nrow][ncol] )
{
*mat = malloc( sizeof(int[nrow][ncol]) );
To ease usage a bit, you can create a temporary pointer to rows, which doesn't require multiple levels of indirection and is therefore much easier to work with:
int (*matrix)[ncol] = *mat[0]; // in the pointed-at 2D array, point at first row
for(size_t r=0; r<nrow; r++) // whatever you want to do with this matrix:
{
for(size_t c=0; c<ncol; c++)
{
matrix[r][c] = 1; // much more convenient syntax than (**mat)[r][c]
}
}
From main, you'll have to call the code like this:
size_t row = 3;
size_t col = 4;
int (*mat)[row][col];
genmat(row, col, &mat);
Example:
#include <stdio.h>
#include <stdlib.h>
void genmat (size_t nrow, size_t ncol, int (**mat)[nrow][ncol] )
{
*mat = malloc( sizeof(int[nrow][ncol]) );
int (*matrix)[ncol] = *mat[0];
for(size_t r=0; r<nrow; r++)
{
for(size_t c=0; c<ncol; c++)
{
matrix[r][c] = 1;
}
}
}
void printmat (size_t nrow, size_t ncol, int mat[nrow][ncol])
{
for(size_t r=0; r<nrow; r++)
{
for(size_t c=0; c<ncol; c++)
{
printf("%d ", mat[r][c]);
}
printf("\n");
}
}
int main (void)
{
size_t row = 3;
size_t col = 4;
int (*mat)[row][col];
genmat(row, col, &mat);
printmat(row, col, *mat);
free(mat);
return 0;
}
Please note that real code needs to address the case where malloc returns NULL.
I assume the problems is withint **mat = (int**) malloc(sizeof(int)*ncol*nrow);
You are trying to allocate the a 2D array right? But this isn't the correct method to allocate the memory. You can't allocate the whole chunk of memory one short.
What you should be doing here is, allocate the memory for all the rows(basically pointer to store the column address) and then for columns
int **mat= (int **)malloc(nrow * sizeof(int *));
for (i=0; i<nrow; i++)
mat[i] = (int *)malloc(ncol * sizeof(int));
Refer this link for more info http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/
This question already has answers here:
Allocating 2-D array in C
(2 answers)
Closed 8 years ago.
I need to create a two dimensional array. Presently I created it as
int a[100][100]
but I need to allocate the memory dynamically using malloc in C language. I used the code
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n=6, m=5, i, j;
int **a = malloc(n * sizeof(int *));
for(i = 0; i < m; i++)
a[i] = malloc(m * sizeof(int));
for( i = 1; i <= n; i++ )
{
for( j = 1; j <= m; j++ )
{
scanf("%d %d",&a[i][j]);
}
}
return 0;
}
but now while inputting the elements into the array it shows SEGMENTATION ERROR.
You say in the comments that n is the number of rows. So you need to allocate n rows each of length m. Therefore, the second for loop condition should be i < n. Also, you should check the return value of malloc for NULL in case it fails to allocate memory. I suggest the following change -
long long **a = malloc(n * sizeof(*a));
for(i = 0; i < n; i++)
a[i] = malloc(m * sizeof(*a[i]));
Please note that a multi-dimensional array is not a fundamentally new type. It's simply an array of elements where each element itself is an array (for a 2D array), an array of arrays (for a 3D) array and so on. If you are using C99, you can allocate your array cleanly and succinctly as
int nrow = 4; // number of rows
int ncol = 8; // number of columns
// define arr to be a pointer to an array of ncol ints, i.e.,
// arr is a pointer to an object of type (int[ncol])
int (*arr)[ncol] = malloc(sizeof(int[nrow][ncol]));
// check the result of malloc for NULL
if(arr == NULL) {
printf("malloc failed to allocate memory\n");
// handle it
}
// do stuff with arr
for(int i = 0; i < nrow; i++)
for(int j = 0; j < ncol; j++)
arr[i][j] = i + j;
// after you are done with arr
free(arr);
You should also go through this - How do I work with dynamic multi-dimensional arrays in C?
You have three errors: The first is that you allocate only 5 secondary arrays, but in the input you loop over 6 of them.
The second problem is that array indices are zero-based, i.e. the index start at zero and goes to the size minus one.
The third problem is that you scan for two numbers (why?), but you provide only one destination pointer to scanf.
you just need
long *a = malloc(100*100*sizeof(long));
if you want one single big block of memory.
if you want an array of long* pointers and then each array to be in a separate block of memory go like this:
long **a = malloc(100*sizeof(long*));
for (i=0; i<100; i++) {
a[i] = malloc(100*sizeof(long));
}
This creates 1 array of long* pointers, and then 1 array of 100 longs of each pointer, but I'm not sure now if you say a[10][15] for example if it would calculate position of the element as if its a continuous block. Check that out. :)
If you have C99 use Variable Length Array
#include <stdio.h>
#include <stdlib.h>
int main(void) {
unsigned rows, cols;
printf("Enter rows and columns: ");
fflush(stdout);
scanf("%u%u", &rows, &cols);
int (*a)[cols]; // pointer to VLA
a = malloc(rows * cols * sizeof a[0][0]);
if (a) {
for (unsigned r = 0; r < rows; r++) {
for (unsigned c = 0; c < cols; c++) {
a[r][c] = r*c;
}
}
printf("the element at [4, 2] is %d\n", a[4][2]);
free(a);
}
return 0;
}
Otherwise, you need to calculate the indexing manually.
There are many problems in your code
First, you need long long a[100][100] but you only allocate enough space for ints
a[i] = malloc(m * sizeof(int));
You're also accessing arrays out-of-bound. Indexes start from 0 to array_length-1.
Another problem is that you scanf 2 int values but only provide the address for 1.
scanf("%d %d",&a[i][j]);
You can allocate a 100-element array of pointers, each points to an array of another 100-element array but that's not good because it takes time to do 100 mallocs, and the resulting memory most probably isn't contiguous, which makes it cache unfriendly. There are also a small memory overhead too because the memory allocator must round it up to the nearest block size and this is most probably powers of 2, which may be large as you allocate more and more elements in the first dimension.
You should declare a 1D array of size 100*100 instead. This will be much faster and improve cache coherency. To get the element at a[i][j] just do a[i*WIDTH + j]
long long* a = malloc(WIDTH*HEIGHT*sizeof(long long));
for (i = 0; i < WIDTH*HEIGHT; i++)
{
scanf("%lld ",&a[i]);
}
for (i = 0; i < HEIGHT; i++)
{
for (j = 0; j < WIDTH; j++)
{
printf("%lld ", a[i*WIDTH + j]);
}
printf("\n");
}
I am trying to dynamically allocate a 2D array, put some values, and print output. However it seems that I am making mistake in getting input to program in atoi() function.
Basically when we assign a static 2D array, we declare it as say int a [3][3]. So 3*3 units if int, that much memory gets allocated. Is same thing holds for allocating dynamic array as well?
Here is my code:
#include<stdio.h>
#include<stdlib.h>
int main(int arg,char* argv)
{
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
int rows =3;
int col=3;
int i,j;
int (*arr)[col] = malloc(sizeof (*arr)*rows);
int *ptr = &(arr[0][0]);
int ct=1;
for (i=0;i<rows;i++)
{
for(j=0;j<col;j++)
{
arr[i][j]=ct;
ct++;
}
}
printf("printing array \n");
for (i=0;i<rows;i++)
{
for(j=0;j<col;j++)
{
printf("%d \t",arr[i][j]);
}
printf("\n");
}
free(arr);
return (0);
}
Program crashes in runtime. Can someone comment?
Try to change the third line to:
int main(int arg,char **argv)
The common method to use dynamic matrices is to use a pointer to pointer to something, and then allocate both "dimensions" dynamically:
int **arr = malloc(sizeof(*arr) * rows);
for (int i = 0; i < rows; ++i)
arr[i] = malloc(sizeof(**arr) * col);
Remember that to free the matrix, you have to free all "rows" in a loop first.
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
int rows =3;
int col=3;
int i,j;
You are defining rows and col twice.... that would never work!
With traditional C, you can only have the array[][] structure for multiple dimension arrays work with compile time constant values. Otherwise, the pointer arithmetic is not correct.
For dynamically sized multi dimensional arrays (those where rows and cols are determined at runtime), you need to do additional pointer arithmetic of this type:
int *a;
int rows=3;
int cols=4;
a = malloc(rows * cols * sizeof(int));
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
a[i*rows + j] = 1;
free(a);
Alternatively, you can use double indirection and have an array of pointers each pointing to a one dimensional array.
If you are using GCC or any C99 compiler, dynamic calculation of multiple dimension arrays is simplified by using variable length arrays:
// This is your code -- simplified
#include <stdio.h>
int main(int argc, const char * argv[])
{
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
// you can have a rough test of sanity by comparing rows * col * sizeof(int) < SIZE_MAX
int arr[rows][col]; // note the dynamic sizing of arr here
int ct=1;
for (int i=0;i<rows;i++)
for(int j=0;j<col;j++)
arr[i][j]=ct++;
printf("printing array \n");
for (int i=0;i<rows;i++)
{
for(int j=0;j<col;j++)
{
printf("%d \t",arr[i][j]);
}
printf("\n");
}
return 0;
} // arr automatically freed off the stack
With a variable length array ("VLA"), dynamic multiple dimension arrays in C become far easier.
Compare:
void f1(int m, int n)
{
// dynamically declare an array of floats n by m size and fill with 1.0
float *a;
a = malloc(m * n * sizeof(float));
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
a[i*n + j] = 1.0;
free(a);
}
With VLA you can write to do the same:
void f2(int m, int n)
{
// Use VLA to dynamically declare an array of floats n by m size and fill with 1.0
float a[m][n];
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
a[i][j] = 1.0;
}
Be aware that unlike malloc / free VLA's handling of requesting a size larger than what is available on the stack is not as easily detected as using malloc and testing for a NULL pointer. VLA's are essentially automatic variables and have similar ease and restrictions.
VLA's are better used for smaller data structures that would be on the stack anyway. Use the more robust malloc / free with appropriate detection of failure for larger data structures.
If you are not using a fairly recent vintage C compiler that supports C99 -- time to get one.
I want to dynamically allocate 1 dimension of a 2D array (the other dimension is given). Does this work:
int NCOLS = 20;
// nrows = user input...
double *arr[NCOLS];
arr = (double *)malloc(sizeof(double)*nrows);
and to free it:
free(arr)
Not quite -- what you've declared is an array of pointers. You want a pointer to an array, which would be declared like this:
double (*arr)[NCOLS];
Then, you'd allocate it like so:
arr = malloc(nrows * sizeof(double[NCOLS]));
It can then be treated as a normal nrows by NCOLS 2D array. To free it, just pass it to free like any other pointer.
In C, there's no need to cast the return value of malloc, since there's an implicit cast from void* to any pointer type (this is not true in C++). In fact, doing so can mask errors, such as failing to #include <stdlib.h>, due to the existence of implicit declarations, so it's discouraged.
The data type double[20] is "array 20 of double, and the type double (*)[20] is "pointer to array 20 of double". The cdecl(1) program is very helpful in being able to decipher complex C declarations (example).
An example:
#include <stdio.h>
#include <stdlib.h>
#define COLS 2
void func(int (**arr)[COLS], int rows)
{
int i, j;
*arr = malloc(sizeof(int[COLS]) * rows);
printf("Insert number: \n");
for(i = 0; i < rows; i++)
for(j = 0; j < COLS; j++)
scanf("%d", &(*arr)[i][j]);
for(i = 0; i < rows; i++)
for(j = 0; j < COLS; j++)
printf("%d\n", (*arr)[i][j]);
}
int main(void)
{
int (*arr)[COLS];
func(&arr, 2);
free(arr);
return 0;
}
You have to allocate a new array for each element (each element is a pointer to an array) on the first dimension. You can use a loop for that:
for(i = 0; i < NCOLS; i++)
arr[i] = (double *)malloc(sizeof(double)*nrows);
Do the same to free.
I have a 2 dimensional array dynamically allocated in my C code, in my function main. I need to pass this 2D array to a function. Since the columns and rows of the array are run time variables, I know that one way to pass it is :
-Pass the rows and column variables and the pointer to that [0][0] element of the array
myfunc(&arr[0][0],rows,cols)
then in the called function, access it as a 'flattened out' 1D array like:
ptr[i*cols+j]
But I don't want to do it that way, because that would mean a lot of change in code, since earlier, the 2D array passed to this function was statically allocated with its dimensions known at compile time.
So, how can I pass a 2D array to a function and still be able to use it as a 2D array with 2 indexes like the following?
arr[i][j].
Any help will be appreciated.
See the code below. After passing the 2d array base location as a double pointer to myfunc(), you can then access any particular element in the array by index, with s[i][j].
#include <stdio.h>
#include <stdlib.h>
void myfunc(int ** s, int row, int col)
{
for(int i=0; i<row; i++) {
for(int j=0; j<col; j++)
printf("%d ", s[i][j]);
printf("\n");
}
}
int main(void)
{
int row=10, col=10;
int ** c = (int**)malloc(sizeof(int*)*row);
for(int i=0; i<row; i++)
*(c+i) = (int*)malloc(sizeof(int)*col);
for(int i=0; i<row; i++)
for(int j=0; j<col; j++)
c[i][j]=i*j;
myfunc(c,row,col);
for (i=0; i<row; i++) {
free(c[i]);
}
free(c);
return 0;
}
If your compiler supports C99 variable-length-arrays (eg. GCC) then you can declare a function like so:
int foo(int cols, int rows, int a[][cols])
{
/* ... */
}
You would also use a pointer to a VLA type in the calling code:
int (*a)[cols] = calloc(rows, sizeof *a);
/* ... */
foo(cols, rows, a);
You really can't do this without changing a lot of code. I suggest to wrap this in a structure which contains the limits and then use regexp search'n'replace to fix the accesses.
Maybe use a macro like AA(arr,i,j) (as in Array Access) where arr is the structure.
As far as I know, all you can pass to a function is a pointer to the first element of an array. When you pass an actual array to a function, it is said that "the array decays into a pointer" so no information about the size(s) of the pointed array remains.
A reference to an object of type array-of-T which appears in an expression decays (with three exceptions) into a pointer to its first element; the type of the resultant pointer is pointer-to-T.
I believe you will be able to find more information about this on the C FAQ.
Numerical recipes in C (a book dealing mostly in matrices) suggests a way to do this cleanly and still deal with 2D matrices. Check out the section 1.2 "Matrices and 2D arrays" and the method convert_matrix().
Essentially what you need is to allocate a set of pointers to point to your row vectors. And pass this to your function along with the number of rows and columns.
A 2-d array in C is just an array of arrays. Here ya go:
void with_matrix(int **matrix, int rows, int cols) {
int some_value = matrix[2][4];
}
int main(int argc, char **argv) {
int **matrix;
... create matrix ...
with_matrix(matrix, rows, cols);
}
int cols = 4;
int rows = 3;
char** charArray = new char*[rows];
for (int i = 0; i < rows; ++i) {
charArray[i] = new char[cols];
}
// Fill the array
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
charArray[i][j] = 'a';
}
}
// Output the array
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
cout << charArray[i][j];
}
cout << endl;
}