I am trying to allocate a array of char*'s in C.
I know the number of columns in advance, but not the rows
and I want to allocate the rows as and when needed.
I tried to use:
char *(*data)[NUMCOLS]; //declare data as pointer to array NUMCOLS of pointer to char
data = malloc(sizeof(char*));
now, the above line should allocate for data[0] ... correct?
then, I must be able to use the row like
data[0][1] = strdup("test");
.
..
data[0][NUMCOLS-1] = strdup("temp");
I am getting seg fault. I am not able to understand what is wrong here.
can anyone please help.
You haven't allocated enough memory for the things that you want to store. In this particular case, that would be:
data=malloc(sizeof(char*)*NUMCOLS*NUMROWS);
To resize the array, you would use:
data=realloc(data,(size_t)sizeof(char*)*NUMCOLS*NEW_NUMROWS);
More about it (reallocation) here
I would do this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
char ***a = NULL;
a = realloc( a, 1 * sizeof(char **) ); // resizing the array to contains one raw
a[0] = malloc( 3 * sizeof(char *) ); // the new raw will contains 3 element
a[0][0] = strdup("a[0][0]");
a[0][1] = strdup("a[0][1]");
a[0][2] = strdup("a[0][2]");
a = realloc( a, 2 * sizeof(char **) ); // resizing the array to contains two raw
a[1] = malloc( 3 * sizeof(char *) ); // the new raw will contains 3 element
a[1][0] = strdup("a[1][0]");
a[1][1] = strdup("a[1][1]");
a[1][2] = strdup("a[1][2]");
for( int rows=0; rows<2; rows++ ){
for( int cols=0; cols<3; cols++ ){
printf( "a[%i][%i]: '%s'\n", rows, cols, a[rows][cols] );
}
}
}
Related
I'm trying to make a 2D array in C with malloc for "hash map" project but as usual. something happend !
basically I have an issue of accessing the 3rd element of the 1st array arr[0][3], it's super weird (at least to me) ,so let me show you the code
1- create 2D array:
int main(void){
char*** table;
table = malloc(sizeof(char*) * 10);
//create array inside table
table[0] = malloc(sizeof(char) * 20);
return 0;
}
2- assign some strings to 1st array table[0]:
table[0][1] = "test1";
table[0][2] = "test2";
table[0][3] = "test3";
table[0][4] = "test4";
...
table[0][n] = "testn";
3- now the magic happens:
// 10 => n >= 0;
printf("%s", table[0][n]);
returns -> malloc(): corrupted top size Aborted (core dumped)
in that moment I tried everything a noob would do , so somehow I figured out that the 3rd string test3 is the problem.
so if I remove the table[0][3] line, all works great !!
table[0][1] = "test1";
table[0][2] = "test2";
//table[0][3] = "test3";
table[0][4] = "test4";
...
table[0][n] = "testn";
// 10 => n >= 0;
printf("%s", table[0][n]);
returns => "testn";
EDIT
for Vlad From Moscow
that works:
for(int i=0; i<10; i++{
table[0][n] = "test";
//here works
printf("%s", table[0][n];
}
//here also works fine
printf("%s", table[0][3];
You declared the pointer table like
char*** table;
So the expression table[0] used in this statement
table[0] = malloc(sizeof(char) * 20);
has the type char ** and you allocated memory for 20 characters.
If sizeof( char * ) is equal to 8 then the allocated memory can accommodate only two pointers of the type char *. If sizeof( char * ) is equal to 4 then the allocated memory can accommodate only 5 pointers of the type char *.
You need to do something like the following
char*** table;
table = malloc(sizeof(char**) * 10);
//create array inside table
for ( size_t i = 0; i < 10; i++ )
{
table[i] = malloc(sizeof(char *) * 20);
}
These memory allocations will simulate a two dimensional array of the type char * table[10][20].
On the other hand, you could at once allocate memory for a two-dimensional array like
char * ( *table )[20] = malloc( sizeof( char *[10][20] ) );
I'm playing with pointers and stumbled accross this problem. Like in this question I wanted a generic method signature for function foo, therefore I chose void * input as parameter. For testing reasons I casted the void pointer to an int ** pointer to use it like an 2D array.
#include <stdio.h>
#include <stdlib.h>
void * foo(void *input, size_t mySize)
{
for (size_t i = 0; i < mySize; ++i)
{
for (size_t j = 0; j < mySize; ++j)
{
((int **)input)[i*mySize][j] = 10*i+j;
}
}
return input;
}
int main(int argc, char const *argv[])
{
size_t const mySize = 10;
void * myMemory, * testPtr;
myMemory = malloc(mySize * mySize * sizeof(int));
testPtr = foo(myMemory, mySize);
free(testPtr);
return 0;
}
Now I thought that using the [] operator would be same as adding an int to the pointer, e.g. that ((int **)input[i][j] would be the same like `((int **)input)+i+j
But accessing the input array in foo segfaults and using gdb shows me
(gdb) p ((int **)input)[i][j]
Cannot access memory at address 0x0
(gdb) p ((int **)input)+i+j
$25 = (int **) 0x405260
so obviously there is a difference. And therefore I'm confused.
While arrays and pointers are similar, they are not the same.
An array - single or multi dimensional - depicts a continuous chunk of memory, containing a specific datatype. For exampleint arr [10] declares arr as 10 continuous ints in memory. int multi_arr[5][10] declares multi_arr as 5 arrays of 10 continuous ints in memory.
Furthermore, the name arr would be the base address of this array, and passing it to a function would be the same as passing &arr[0].
But this is where the similarities end. A multi dimensional array can't (technically) be cast to a pointer-to-a-pointer and then back again.
If arr above pointed to a block of ints, then dereferencing the first dimension of int ** ptr would lead you to a block of pointers toint. Dereferencing that would not take you deeper into that block, as a multi dimensional array would, rather it could point anywhere.
You allocated a one dimension array with mySize*mySize elements.
int** is an array of pointers to int, what you want is
int **array2d;
int *p;
array2D = malloc(ROWS * sizeof(int*) + ROWS * COLUMNS * sizeof(int));
p = (int*) &array2d[ROWS];
for (size_t i = 0; i < ROWS; ++i)
array2d[i] = &p[i * COLUMNS];
now array2d[row][column] can work.
Or, as already suggested, use a one dimension array and use the array[row * COLUMNS + column] formulae.
I have an an integer array of values and I would like to make a double pointer to point to this array. I assume that this 1D integer array actually represents a 2D array. That is for instance that if I have an int A[2000*12] then I have 12 lines and 2000 rows. The problem is that I do not know how to initialize the pointer to point to the array A. My initial thought was like that:
int A[2000*12];
int **ptr;
ptr=&A[0];
Of course this is not correct. More precisely I get the following error:
incompatible pointer types in assignment
Remove the [0] part:
int A[2000*12];
int **ptr;
ptr = &A;
EDIT:
This however does not solve the problem with getting a 2D array. You still can't access it like
A[1][2] = 10;
because the compiler does not know the length of rows.
My favourite way of initializing a 2D array goes like:
int width = 10;
int height = 20;
int *_a = (int *) malloc(width * height * sizeof(int));
int **a = (int **) malloc(height * sizeof(int *));
The first allocation creates the 2D array, the second one creates an array pointing to each row.
int i, offset = 0;
for (i = 0; i < height; i++, offset += width)
{
a[i] = _a + offset;
}
a[0][0] = 1;
a[0][1] = 2;
a[1][0] = 2;
a[1][1] = 4;
// ...
I am new to C and trying to initialise a 2D array. I need both columns of the array to be char *, as they will contain string values.
I have it working with the array storing ints but for some reason, when I try to store string values when it prints it displays (null). Below is the code for how I am initialising and storing the data as an int (This appears to be working).
int **array;
int row = 0;
array = malloc(2 * sizeof(int*));
int i;
for (i = 0; i < 2; i++)
{
array[i] = malloc(2 * sizeof(int));
}
array[0][0] = i;
array[0][1] = i;
printf("array[0][0]: %i\n", array[0][0]);
Below is how I am doing the above but using string values instead.
char **array;
int row = 0;
array = malloc(2 * sizeof(char*));
int i;
for (i = 0; i < 2; i++)
{
array[i] = malloc(2 * sizeof(char*));
}
array[0][0] = "Test[0][0]";
array[0][1] = "Test[0][1]";
printf("array[0][0]: %s\n", array[0][0]);
Thanks for any help you can provide.
You have the wrong level of pointer indirection, which is over-complicating things.
I think it would be easier for you if you thought of the array as an array of structures, each structure holding two pointers:
struct row {
char *column1;
char *column2;
};
then it's (hopefully) clearer that once you've allocated an array of struct row, you have two pointers in each row, you don't need to allocate room for the pointers themselves.
const size_t num_rows = 1;
struct row * rows = malloc(num_rows * sizeof *rows);
if(rows != NULL)
{
rows[0].column1 = "row 0, column 1";
rows[0].column2 = "row 1, column 2";
}
Note that this uses string literals, otherwise you might need to allocate room for the strings to be stored, depending on where the data comes from.
The num_rows value could of course come from anywhere in your program, I'm just trying to illustrate what controls the number of rows memory is allocated for.
Save yourself the trouble and don't use 2D arrays in C. It's more convenient to use 1D arrays.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
const int nstrings = 2;
const int width = 20; //width of maximum string.
char* array = (char*)malloc(sizeof(char)*nstrings*width);
strcpy(&array[0*width],"Test[0][0]");
strcpy(&array[1*width],"Test[1][0]");
printf("string 0: %s\n", &array[0*width]);
printf("string 1: %s\n", &array[1*width]);
free(array);
}
I have the following C code :
int *a;
size_t size = 2000*sizeof(int);
a = malloc(size);
which works fine. But if I have the following :
char **b = malloc(2000*sizeof *b);
where every element of b has different length.
How is it possible to do the same thing for b as i did for a; i.e. the following code would hold correct?
char *c;
size_t size = 2000*sizeof(char *);
c = malloc(size);
First, you need to allocate array of pointers like char **c = malloc( N * sizeof( char* )), then allocate each row with a separate call to malloc, probably in the loop:
/* N is the number of rows */
/* note: c is char** */
if (( c = malloc( N*sizeof( char* ))) == NULL )
{ /* error */ }
for ( i = 0; i < N; i++ )
{
/* x_i here is the size of given row, no need to
* multiply by sizeof( char ), it's always 1
*/
if (( c[i] = malloc( x_i )) == NULL )
{ /* error */ }
/* probably init the row here */
}
/* access matrix elements: c[i] give you a pointer
* to the row array, c[i][j] indexes an element
*/
c[i][j] = 'a';
If you know the total number of elements (e.g. N*M) you can do this in a single allocation.
The typical form for dynamically allocating an NxM array of type T is
T **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * M);
}
}
If each element of the array has a different length, then replace M with the appropriate length for that element; for example
T **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * length_for_this_element);
}
}
Equivalent memory allocation for char a[10][20] would be as follows.
char **a;
a=malloc(10*sizeof(char *));
for(i=0;i<10;i++)
a[i]=malloc(20*sizeof(char));
I hope this looks simple to understand.
The other approach would be to allocate one contiguous chunk of memory comprising header block for pointers to rows as well as body block to store actual data in rows. Then just mark up memory by assigning addresses of memory in body to the pointers in header on per-row basis. It would look like follows:
int** 2dAlloc(int rows, int* columns) {
int header = rows * sizeof(int*);
int body = 0;
for(int i=0; i<rows; body+=columnSizes[i++]) {
}
body*=sizeof(int);
int** rowptr = (int**)malloc(header + body);
int* buf = (int*)(rowptr + rows);
rowptr[0] = buf;
int k;
for(k = 1; k < rows; ++k) {
rowptr[k] = rowptr[k-1] + columns[k-1];
}
return rowptr;
}
int main() {
// specifying column amount on per-row basis
int columns[] = {1,2,3};
int rows = sizeof(columns)/sizeof(int);
int** matrix = 2dAlloc(rows, &columns);
// using allocated array
for(int i = 0; i<rows; ++i) {
for(int j = 0; j<columns[i]; ++j) {
cout<<matrix[i][j]<<", ";
}
cout<<endl;
}
// now it is time to get rid of allocated
// memory in only one call to "free"
free matrix;
}
The advantage of this approach is elegant freeing of memory and ability to use array-like notation to access elements of the resulting 2D array.
If every element in b has different lengths, then you need to do something like:
int totalLength = 0;
for_every_element_in_b {
totalLength += length_of_this_b_in_bytes;
}
return malloc(totalLength);
I think a 2 step approach is best, because c 2-d arrays are just and array of arrays. The first step is to allocate a single array, then loop through it allocating arrays for each column as you go. This article gives good detail.
2-D Array Dynamic Memory Allocation
int **a,i;
// for any number of rows & columns this will work
a = malloc(rows*sizeof(int *));
for(i=0;i<rows;i++)
*(a+i) = malloc(cols*sizeof(int));
malloc does not allocate on specific boundaries, so it must be assumed that it allocates on a byte boundary.
The returned pointer can then not be used if converted to any other type, since accessing that pointer will probably produce a memory access violation by the CPU, and the application will be immediately shut down.