I would like to know why the first two elements are always non-zero. I don't know how more I can describe the question, but this is not allowing me to post the question, so I'm writing this. Not sure if this will work.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 3
void printMatrix(int **m)
{
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++)
printf("%d ", m[i][j]);
printf("\n");
}
}
int main(int argc, char const *argv[])
{
int **matrix;
matrix = (int **) calloc(sizeof(int), SIZE);
for (int i = 0; i < SIZE; ++i)
matrix[i] = (int *) calloc(sizeof(int), SIZE);
printf("%s\n", "Matrix initialized.");
printMatrix(matrix);
return 0;
}
Output:
Matrix initialized.
1371548192 32653 0
0 0 0
0 0 0
You're not allocating enough memory:
matrix = (int **) calloc(sizeof(int), SIZE);
Here you're attempting to create an array of 3 int *, but you're only allocating space for 3 int. If a pointer is larger than an int on your system, which it most likely is, you write past the end of the array when you create the arrays for each row. Writing past the end of allocated memory invokes undefined behavior.
Since you're creating an array of int *, use that for the size of each element:
matrix = calloc(sizeof(int *), SIZE);
Also, don't cast the return value of malloc/realloc/calloc, as that can mask a bug if you forget to #include <stdlib.h>
The code uses calloc(sizeof(int), SIZE), but the actual datatype in the structure is int *, leading to insufficient memory allocation on some systems (mine gives int size as 4 and int * size as 8).
Here's a rewrite suggestion (we'll swap size parameters in the calloc call per its header):
int main(int argc, char const *argv[]) {
int **matrix;
if (!(matrix = calloc(SIZE, sizeof(*matrix)))) {
fprintf(stderr, "calloc failed");
return 1;
}
for (int i = 0; i < SIZE; ++i) {
if (!(matrix[i] = calloc(SIZE, sizeof(*(matrix[i]))))) {
fprintf(stderr, "calloc failed");
return 1;
}
}
printf("%s\n", "Matrix initialized.");
printMatrix(matrix);
return 0;
}
Here, we use *matrix and *matrix[i] instead of hard coding the types int * and int respectively. This can help us avoid bugs and hunting for locations to change code if we need to make type adjustments at some point.
We also check that calloc succeeds by testing that the pointer is non-NULL. Failing to do so can introduce difficult-to-find bugs due to undefined behavior.
Note Do I cast the result of malloc?.
Reference manual describes calloc as:
void* calloc (size_t num, size_t size);
So, calloc takes firstly num of elements and then size of a particular element
Try:
matrix = (int **) calloc(SIZE, sizeof(int *));
Related
I don't really understand why method 1 works but not method 2. I don't really see why it works for characters and not an int.
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
/// WORK (METHODE 1)
char **string_array = malloc(sizeof(char **) * 10);
string_array[0] = "Hi there";
printf("%s\n", string_array[0]); /// -> Hi there
/// DOES NOT WORK (METHODE 2)
int **int_matrix = malloc(sizeof(int **) * 10);
int_matrix[0][0] = 1; // -> Segmentation fault
/// WORK (METHODE 3)
int **int_matrix2 = malloc(sizeof(int *));
for (int i = 0; i < 10; i++)
{
int_matrix2[i] = malloc(sizeof(int));
}
int_matrix2[0][0] = 42;
printf("%d\n", int_matrix2[0][0]); // -> 42
}
In terms of the types, you want to allocate memory for the type "one level up" from the pointer you're assigning it to. For example, an int pointer (an int*), points to one or more ints. That means, when you allocate space for it, you should allocate based on the int type:
#define NUM_INTS 10
...
int* intPtr = malloc(NUM_INTS * sizeof(int));
// ^^ // we want ints, so allocate for sizeof(int)
In one of your cases, you have a double int pointer (an int**). This must point to one or more int pointers (int*), so that's the type you need to allocate space for:
#define NUM_INT_PTRS 5
...
int** myDblIntPtr = malloc(NUM_INT_PTRS * sizeof(int*));
// ^^ "one level up" from int** is int*
However, there's an even better way to do this. You can specify the size of your object it points to rather than a type:
int* intPtr = malloc(NUM_INTS * sizeof(*intPtr));
Here, intPtr is an int* type, and the object it points to is an int, and that's exactly what *intPtr gives us. This has the added benefit of less maintenance. Pretend some time down the line, int* intPtr changes to int** intPtr. For the first way of doing things, you'd have to change code in two places:
int** intPtr = malloc(NUM_INTS * sizeof(int*));
// ^^ here ^^ and here
However, with the 2nd way, you only need to change the declaration:
int** intPtr = malloc(NUM_INTS * sizeof(*intPtr));
// ^^ still changed here ^^ nothing to change here
With the change of declaration from int* to int**, *intPtr also changed "automatically", from int to int*. This means that the paradigm:
T* myPtr = malloc(NUM_ITEMS * sizeof(*myPtr));
is preferred, since *myPtr will always refer to the correct object we need to size for the correct amount of memory, no matter what type T is.
Others have already answered most of the question, but I thought I would add some illustrations...
When you want an array-like object, i.e., a sequence of consecutive elements of a given type T, you use a pointer to T, T *, but you want to point to objects of type T, and that is what you must allocate memory for.
If you want to allocate 10 T objects, you should use malloc(10 * sizeof(T)). If you have a pointer to assign the array to, you can get the size from that
T * ptr = malloc(10 * sizeof *ptr);
Here *ptr has type T and so sizeof *ptr is the same as sizeof(T), but this syntax is safer for reasons explained in other answers.
When you use
T * ptr = malloc(10 * sizeof(T *));
you do not get memory for 10 T objects, but for 10 T * objects. If sizeof(T*) >= sizeof(T) you are fine, except that you are wasting some memory, but if sizeof(T*) < sizeof(T) you have less memory than you need.
Whether you run into this problem or not depends on your objects and the system you are on. On my system, all pointers have the same size, 8 bytes, so it doesn't really matter if I allocate
char **string_array = malloc(sizeof(char **) * 10);
or
char **string_array = malloc(sizeof(char *) * 10);
or if I allocate
int **int_matrix = malloc(sizeof(int **) * 10);
or
int **int_matrix = malloc(sizeof(int *) * 10);
but it could be on other architectures.
For your third solution, you have a different problem. When you allocate
int **int_matrix2 = malloc(sizeof(int *));
you allocate space for a single int pointer, but you immediately treat that memory as if you had 10
for (int i = 0; i < 10; i++)
{
int_matrix2[i] = malloc(sizeof(int));
}
You can safely assign to the first element, int_matrix2[0] (but there is a problem with how you do it that I get to); the following 9 addresses you write to are not yours to modify.
The next issue is that once you have allocated the first dimension of your matrix, you have an array of pointers. Those pointers are not initialised, and presumably pointing at random places in memory.
That isn't a problem yet; it doesn't do any harm that these pointers are pointing into the void. You can just point them to somewhere else. This is what you do with your char ** array. You point the first pointer in the array to a string, and it is happy to point there instead.
Once you have pointed the arrays somewhere safe, you can access the memory there. But you cannot safely dereference the pointers when they are not initialised. That is what you try to do with your integer array. At int_matrix[0] you have an uninitialised pointer. The type-system doesn't warn you about that, it can't, so you can easily compile code that modifies int_matrix[0][0], but if int_matrix[0] is pointing into the void, int_matrix[0][0] is not an address you can safely read or write. What happens if you try is undefined, but undefined is generally was way of saying that something bad will happen.
You can get what you want in several ways. The closest to what it looks like you are trying is to implement matrices as arrays of pointers to arrays of values.
There, you just have to remember to allocate the arrays for each row in your matrix as well.
#include <stdio.h>
#include <stdlib.h>
int **new_matrix(int n, int m)
{
int **matrix = malloc(n * sizeof *matrix);
for (int i = 0; i < n; i++)
{
matrix[i] = malloc(m * sizeof *matrix[i]);
}
return matrix;
}
void init_matrix(int n, int m, int **matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int **matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int **matrix = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
return 0;
}
Here, each row can lie somewhere random in memory, but you can also put the row in contiguous memory, so you allocate all the memory in a single malloc and compute indices to get at the two-dimensional matrix structure.
Row i will start at offset i*m into this flat array, and index matrix[i,j] is at index matrix[i * m + j].
#include <stdio.h>
#include <stdlib.h>
int *new_matrix(int n, int m)
{
int *matrix = malloc(n * m * sizeof *matrix);
return matrix;
}
void init_matrix(int n, int m, int *matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[m * i + j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int *matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[m * i + j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int *matrix = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
return 0;
}
With the exact same memory layout, you can also use multidimensional arrays. If you declare a matrix as int matrix[n][m] you will get what amounts to an array of length n where the objects in the arrays are integer arrays of length m, exactly as on the figure above.
If you just write that expression, you are putting the matrix on the stack (it has auto scope), but you can allocate such matrices as well if you use a pointer to int [m] arrays.
#include <stdio.h>
#include <stdlib.h>
void *new_matrix(int n, int m)
{
int(*matrix)[n][m] = malloc(sizeof *matrix);
return matrix;
}
void init_matrix(int n, int m, int matrix[static n][m])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int matrix[static n][m])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int(*matrix)[m] = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
int(*matrix2)[m] = new_matrix(2 * n, 3 * m);
init_matrix(2 * n, 3 * m, matrix2);
print_matrix(2 * n, 3 * m, matrix2);
return 0;
}
The new_matrix() function returns a void * because the return type cannot depend on the runtime arguments n and m, so I cannot return the right type.
Don't let the function types fool you, here. The functions that take a matrix[n][m] argument do not check if the matrix has the right dimensions. You can get a little type checking with pointers to arrays, but pointer decay will generally limit the checking. The last solution is really only different syntax for the previous one, and the arguments n and m determines how the (flat) memory that matrix points to is interpreted.
The method 1 works only becuse you assign the char * element of the array string_array with the reference of the string literal `"Hi there". String literal is simply a char array.
Try: string_array[0][0] = 'a'; and it will fail as well as you will dereference not initialized pointer.
Same happens in method 2.
Method 3. You allocate the memory for one int value and store the reference to it in the [0] element of the array. As the pointer references the valid object you can derefence it (int_matrix2[0][0] = 42;)
I've been unable to find any question regarding this, and I think I'm going a bit crazy trying to figure this out.
I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
int cmp_int(const void *a, const void *b)
{
return * (int *)a - * (int *)b;
}
int main(int argc, char *argv[])
{
int n = 10;
int **arr = calloc(n, sizeof(int *));
srand((unsigned int) time(NULL));
for (int i = n-1; i >= 0; i--) {
arr[i] = calloc(1, sizeof(int));
*(arr[i]) = rand() % 1000;
}
for (int i = 0; i < n; i++)
printf("%d ", *(arr[i]));
printf("\n");
qsort(arr, 10, sizeof(void *), cmp_int);
for (int i = 0; i < n; i++)
printf("%d ", *(arr[i]));
printf("\n");
free(arr);
return 0;
}
It's super basic, right? According to the manpage, the first argument is the pointer to the base element and the third argument is the size. However, I fail to get the array as a sorted result. I'm still really confused as to what the first and third argument to qsort should be since I suspect that that's where the fault is.
Any help is appreciated.
Thanks.
Edit: I should add that this code obviously does no error checking and that I was trying to test qsort with a double-pointer array of integers, so while yes I could use a regular array that was not the intended purpose of this code (it’s actually part of a bigger segment in a separate program).
Your program makes my head hurt. The reason you're not getting a correct sort is that the comparison function is wrong. It would need to be return **(int **)a - **(int **)b; to get a correct result.
However it's not worth fixing the problem that way. A list of at least some of the issues:
If you don't use argc and argv, don't declare them.
Cast in the srand call is unnecessary.
int comparison by subtraction is a bad idea because it can overflow.
calloc returns should always be checked for null (out of memory) results.
calloc isn't needed at all. Use a variable length array.
There's no need to allocate an array of pointers to ints. Just allocate an array of ints. Then your comparison works as-is.
The qsort call uses a hard constant 10 rather than n.
It's less error prone to give the element size by dereferencing the array name.
At the end you free the "spine" array but never the integer elements.
You should factor out a function to print the array.
Here's a version that addresses these.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int cmp_int(const void *va, const void *vb)
{
int a = *(int *)va, b = *(int *) vb;
return a < b ? -1 : a > b ? +1 : 0;
}
void print(int *a, int n) {
for (int i = 0; i < n; ++i) printf("%d ", a[i]);
printf("\n");
}
int main(void)
{
int n = 10, a[n];
srand(time(0));
for (int i = 0; i < n; ++i) a[i] = rand() % 1000;
print(a, n);
qsort(a, n, sizeof a[0], cmp_int);
print(a, n);
return 0;
}
The problem you are having is failing to account for one additional level of indirection created by allocating for a block of pointers with int **arr = calloc (n, sizeof *arr); and then allocating storage for a single int to each pointer with arr[i] = calloc (1, sizeof *arr[i]).
Since the int compare (const void *a, const void *b) compare function for qsort expects a pointer to the elements of the array being sorted, both a and b above will be pointer-to-pointer to int in your case requiring 2 levels of indirection be dereferenced before the integer values can be compared.
Rather than cmp_int, you actually need a cmp_int_ptr compare function. It can be written as:
int cmp_int_ptr (const void *a, const void *b)
{
int *ai = *(int * const *)a,
*bi = *(int * const *)b;
return (*ai > *bi) - (*ai < *bi);
}
(note: the two levels of indirection in the cast (int * const *)... which can also be written as (int **), but to correspond to the parameter type (const void *) the (int * const *) is proper)
Putting that in place, adding validations for each allocation and cleaning up your calloc type-size specification by using the dereferenced pointer itself to set type-size, you can do:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
int cmp_int_ptr (const void *a, const void *b)
{
int *ai = *(int * const *)a,
*bi = *(int * const *)b;
return (*ai > *bi) - (*ai < *bi);
}
int main (void) {
int n = 10;
int **arr = calloc (n, sizeof *arr);
if (!arr) {
perror ("calloc-arr");
return 1;
}
srand((unsigned int) time(NULL));
for (int i = 0; i < n; i++) {
if (!(arr[i] = calloc (1, sizeof *arr[i]))) {
perror ("calloc-arr[i]");
return 1;
}
*(arr[i]) = rand() % 1000;
}
for (int i = 0; i < n; i++)
printf (" %d", *(arr[i]));
putchar ('\n');
qsort (arr, 10, sizeof *arr, cmp_int_ptr);
for (int i = 0; i < n; i++) {
printf (" %d", *(arr[i]));
free (arr[i]); /* don't forget to free your int allocated */
}
putchar ('\n');
free(arr); /* now free pointers */
}
Example Use/Output
$ ./bin/qsortptrtoint
654 99 402 264 680 534 155 533 397 678
99 155 264 397 402 533 534 654 678 680
Look things over and let me know if you have questions.
What is the best way to return a multidimensional array from a function in c ?
Say we need to generate a multidimensional array in a function and call it in main, is it best to wrap it in a struct or just return a pointer to memory on the heap ?
int *create_array(int rows, int columns){
int array[rows][columns] = {0};
return array;
}
int main(){
int row = 10;
int columns = 2;
create_array(row,columns);
}
The code above, is just to sketch out the basic program I have in mind.
This is wrong:
int *create_array(int rows, int columns){
int array[rows][columns] = {0};
return array;
}
and should produce a warning like this:
prog.c:2:6: note: (near initialization for 'array')
prog.c:3:13: warning: return from incompatible pointer type [-Wincompatible-pointer-types]
return array;
^~~~~
prog.c:3:13: warning: function returns address of local variable [-Wreturn-local-addr]
since you are returning the address of an automatic variable; its lifetime ends when its corresponding function terminates.
You should either declare a double pointer in main(), pass it through the function, dynamically allocate memory for it and return that pointer. Or you could create the array in main() and pass the double pointer to the function.
I want to know ways to allocate multidimensional arrays on the heap and pass them around
For allocating memory on the heap you could use one of these two methods, which involve pointers:
#include <stdio.h>
#include <stdlib.h>
// We return the pointer
int **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i, **array;
array = malloc(N*sizeof(int *));
for(i = 0 ; i < N ; i++)
array[i] = malloc( M*sizeof(int) );
return array;
}
// We don't return the pointer
void getNoReturn(int*** array, int N, int M) {
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
*array = malloc(N*sizeof(int *));
for(i = 0 ; i < N ; i++)
(*array)[i] = malloc( M*sizeof(int) );
}
void fill(int** p, int N, int M) {
int i, j;
for(i = 0 ; i < N ; i++)
for(j = 0 ; j < M ; j++)
p[i][j] = j;
}
void print(int** p, int N, int M) {
int i, j;
for(i = 0 ; i < N ; i++)
for(j = 0 ; j < M ; j++)
printf("array[%d][%d] = %d\n", i, j, p[i][j]);
}
void freeArray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
int main(void)
{
int **p;
//getNoReturn(&p, 2, 5);
p = get(2, 5);
fill(p ,2, 5);
print(p, 2, 5);
freeArray(p ,2);
return 0;
}
Pick whichever suits best your style.
What is the best way to return a multidimensional array from a function in c ?
My recommendation is to avoid doing that, and avoid multidimensional arrays in C (they are unreadable and troublesome).
I would recommend making your matrix type your proper abstract data type, represented by some struct ending with a flexible array member:
struct mymatrix_st {
unsigned nbrows, nbcolumns;
int values[];
};
Here is the creation function (returning a properly initialized pointer to dynamic memory):
struct mymatrix_st*
create_matrix(unsigned mnbrows, unsigned mnbcolumns) {
if (mnbrows > UINT_MAX/4 || mnbcolumns > UINT_MAX/4
||(unsigned long)mnbrows * (unsigned long)mnbcolums
> UINT_MAX) {
fprintf(stderr, "too big matrix\n");
exit(EXIT_FAILURE);
};
size_t sz = sizeof(struct mymatrix_st)+(mnbrows*mnbcolumns*sizeof(int));
struct mymatrix_st*m = malloc(sz);
if (!m) {
perror("malloc mymatrix"); exit(EXIT_FAILURE); };
m->nbrows = mnbrows;
m->nbcolumns = mnbcolumns;
for (unsigned long ix=(unsigned long)mnbrows * (unsigned long)mnbcolumns-1;
ix>=0; ix--)
m->values[ix] = 0;
return m;;
} /*end create_matrix*/
It is on purpose that struct mymatrix_st don't contain any interior pointer. You can and should use free to destroy it.
Here is the accessor function; make it a static inline function and define it in the same header declaring struct mymatrix_st and create_matrix, e.g.
static inline int getmatrix(struct mymatrix_st*m, unsigned row, unsigned col) {
if (!m) {
fprintf(stderr, "getmatrix with no matrix\n");
exit(EXIT_FAILURE);
};
if (row >= m->nbrows || col >= m->nbcolumns){
fprintf(stderr, "getmatrix out of bounds\n");
exit(EXIT_FAILURE);
};
return m->values[row*m->nbcolumns + col];
}
I leave up to you to define and implement the other operations on your abstract struct mymatrix_st type.
(you could adapt the code, perhaps removing the out of bound check, but I don't recommend unsafe code)
int** create_array(int rows, int columns){
int** array = malloc(rows * sizeof(int*));
int i;
for (i=0; i<rows; i++)
array[i] = malloc(columns * sizeof(int));
return array;
}
should do the trick. If you use int array[rows][columns]; then it's dead as soon as the functiom returns, and you get a UB. You should at least use dynamic memory allocation.
You can't return an array, but you can return a regular pointer and document that the callee may treat it as a pointer to a multidimensional array of the dimensions that it had passed to the caller.
(Note that the returned pointer must point to dynamic or static, but not automatic memory--don't return pointers to local variables!)
It takes some slightly wordy casts and possibly a macro but it's doable:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void*
multi(int R, int C)
{
return calloc ( 1, sizeof(int[R][C]) ); //or sizeof(int)*R*C
}
int main()
{
int (*r_)[3][4] = multi(3,4);
if(!r_) return EXIT_FAILURE;
#define r (*r_)
//emulate C++ a reference -- r now behaves as an `int r[3][4];`
//Test that addresses advance as they would in a multi-d array
int local[3][4];
assert(&local[1][0]-&local[0][0] == 4); //base example
assert(&r[1][0]-&r[0][0] == 4); //"returned" multi-d array
free(r); //or free(&r) or free(r_) -- here it shouldn't matter
#undef r
return 0;
}
Note that an array of pointers is not the same thing as a multi-d array.
A true multi-d array is one contiguous block, whereas an array of pointers (though usable with the same indexing syntax) has much worse locality of reference, so this might be preferable over returning pointers to pointers if you want better performance.
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.
How to find number of rows in dynamic 2D char array in C?
Nothing from there.
tried with following code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int k = 97;
void foo(char **a)
{
int i = 0;
for(i=0; a[i] != NULL; ++i)
printf("i = %d\n", i);
}
void strcpyo(char* a, char*b){
int i=0;
for(i=0;b[i]!='\0';i++){
a[i]=b[i];
}
a[i]='\0';
}
void strcpym(char* a, char*b){
int i=0;
for(i=0;b[i]!='\0';i++);
memcpy(a,b,i+1);
}
void freee(char** ptr){
int i;
for(i = 0;i < k; ++i)
{
free(ptr[i] );
}
free(ptr);
}
void alloc(char ***p)
{
*p = (char **)malloc(k * sizeof(char *));
int i,j;
for(j=0;j<k;j++)
{
// for(i = 0;i < j; ++i)
{
(*p)[j] = (char *)malloc(11 * sizeof(char));
strcpy((*p)[j],"paicharan");
}
//printf("j = %d ", j);
//foo(p);
}
}
int main()
{
char **p;
alloc(&p);
#if 0
char **p = (char **)malloc(k * sizeof(char *));
int i,j;
for(j=0;j<k;j++)
{
for(i = 0;i < j; ++i)
{
p[i] = (char *)malloc(11 * sizeof(char));
strcpy(p[i],"paicharan");
}
printf("j = %d ", j);
foo(p);
}
#endif
foo(p);
freee(p);
return 0;
}
The code in #if 0 #endif works perfectly, but if I do create arrays in function alloc(char**) it's giving the wrong answer for odd number of rows in array. Can anybody explain why?
ie. for k= odd number it gives out wrong answer but for even number its correct.
Your code depends on Undefined Behaviour to work correctly i.e. it'll work only by chance. This has got nothing to do with even or odd count of elements.
In the void alloc(char ***p) function you allocate memory for k pointer to pointer to char: char**. Then you fill all of the k pointers with new valid char* pointers i.e. none of them are NULL. Later in void foo(char **a) you do for(i=0; a[i] != NULL; ++i); since a[k - 1] was non-null, it'll iterate over them correctly. BUT after that a[k] may or may not be NULL, you never know what is in there. Also accessing what is beyond the array you allocated is undefined behaviour (due to out of bounds access).
Making k + 1 elements and setting the kth element to NULL makes this work; make sure you free all of k + 1 elements and not leak the last sentinal element.
Since you told that the code wraped inside the macro works fine, I've ignored that; don't know if there's UB there too. If you're doing this exercise to learn, it's fine. If you are planning to do some other project, try to reuse some existing C library which already gives these facilities.