I'm trying to declare arrays with a variable size, given by user input.
So far I have something like this:
typedef struct _object{
int rowsAmount;
int columsAmount;
int* rows;
int* colums;
} object;
object* newObject(int ra, int ca){
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->rows = [ra];
o->colums = [ca];
return o;
}
int main(){
newObject(3,4);
}
I expected this wouldn't work, but I want something like this, and I don't know how to do it.
It looks like you're basically implementing a dynamic Matrix object here. You want something like:
typedef struct _object{
int rowsAmount;
int columsAmount;
int* matrix;
int** rows;
} object;
object* newObject(int ra, int ca){
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->matrix = malloc(ra * ca * sizeof(int));
o->rows = malloc(ra * sizeof(int*));
for (size_t i = 0; i != ra; ++i) o->rows[i] = o->matrix + (i * ca);
return o;
}
You should also create a destructor function destroyObject, which similarly frees all the memory allocated for o and o->matrix.
Edit:
However, your comment that:
"I'm just trying to learn c, this is only about the setting the size.
I just happened to try it with 2 arrays"
...makes this question somewhat confusing, because it indicates you are not, in fact, trying to create a matrix (2D array) despite your use of "row"/"column" terminology here, but that you simply want to understand how to dynamically allocate arrays in C.
If that's the case, an array in C is dynamically allocated using a pointer variable and malloc:
size_t array_size = 10; /* can be provided by user input */
int* array = malloc(sizeof(int) * array_size);
And then later, the dynamically-allocated array must be freed once you are finished working with it:
free(array);
To dynamically allocate a 2d array of data in C:
Allocate the memory for the entire data. That memory is pointed to by arrayData.
Allocate an 1D Array of pointers one for each row
Point those pointers to the memory address corresponding each row
Code:
int *arrayData = malloc(sizeof(int) * rows * columns);
int **array = malloc(sizeof(int*) * rows);
for(int i=0; i < rows;++i){
array[i] = arrayData + i * columns;
}
You can now access the memory as array[row][col].
You can create a array with size input from user with out a structure.
int *array1;
int size;
// get input from user
array1 = malloc(sizeof(int)*size);
// do your stuff
free(array1);
if you want a 2D array,
int **array2;
int row, col;
int i;
array2 = malloc(sizeof(int*)*row);
for(i=0;i<row;++i)
array2[i] = malloc(sizeof(int)*col);
//use the array
for(i=0;i<row;++i)
free(array2[i]);
free(array2);
if you really need a structure array, then allocate memory for it in your newObject() function
typedef struct _object{
int rowsAmount;
int columsAmount;
int** array;
//int* colums;
} object;
object* newObject(int ra, int ca){
int i;
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->array = malloc(sizeof(int*)*ra);
for(i=0;i<ra;i++)
o-<array[i]=malloc(sizeof(int)*ca);
return o;
}
int main(){
newObject(3,4);
}
I think that quite often people use dynamic memory allocation when scoped variables can be used instead. For example, array sized from user's input can be allocated on stack without using malloc/free:
int array_size;
scanf("%d", &array_size);
if (array_size > 0) {
/* Allocate array on stack */
float array[array_size];
/* ... do smth with array ... */
}
/* Out of scope, no need to free array */
Of course if your data block is huge, heap memory is a must, but for small allocations scopes are just fine.
Easiest way is to use boost::multi_array
Not only will you get any number of dimensions, it's also stored very efficiently as a single contiguous block of memory rather than n dimensional array.
CPU's are designed to traverse arrays quickly, and you could potentially utilise caching/prefetch/pipelining features of the compiler using this.
Eg
// 2 dimensions
int xDim;
int yDim;
cin >> xDim; // From user..
cin >> yDim;
// Initialise array
boost::multi_array<int,2> my2dgrid(boost::extents[xDim][yDim]);
// Iterate through rows/colums
for(int j = 0 ; j < yDim-1; j++) { // Row traversal
for(int i = 0 ; i < xDim-1; i++) { // Column traversal
int value = grid[j][i]; // Get a value
grid[j][i] = 123; // set a value
// Do something...
}
#include <stdio.h>
#include <stdlib.h>
typedef struct _object{
int rowsAmount;
int columsAmount;
int **rows;
// int* colums;
} object;
object* newObject(int ra, int ca){
int r;
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->rows = (int **)malloc(ra*sizeof(int *));
for(r=0;r<ra;++r)
o->rows[r] = (int*)malloc(ca*sizeof(int));
return o;
}
int main(){
object *obj= newObject(3,4);
obj->rows[2][3]=5;
return 0;
}
Related
I created a struct called PLAYER and I want to create an list that stores the pointers to the PLAYER object.
If I want to accomplish it with
PLAYER **ptr = malloc(10*sizeof(PLAYER *));
How can I assign the pointers to each index? I tried:
PLAYER *a;
PLAYER *b;
ptr[0] = a;
ptr[1] = b;
1.This seems to work. Can I get some explanation on the memory address behind it?
I also tried:
ptr = a;
//increase the address and assign b
ptr += sizeof(PLAYER *);
ptr = b;
2.This does not work correctly I think. Can I see a correct way of assign the list without using the [] brackets?
3.If I allocate only one entry's size and assign multiple ones:
PLAYER **ptr = malloc(1*sizeof(PLAYER *));
ptr[0] = a;
ptr[1] = b;
I can get these PLAYER object by using ptr[0] ptr[1], but will this cause any problems like overwrite other memories?
4.If I use [] brackets, do I need to malloc at each index in order to use it?
PLAYER *ptr[10];
for(int i = 0; i < 10; i++)
ptr[i] = malloc(sizeof(PLAYER *));
5.Do I need to free an array after using it? such as:
char ptr[10] = "abc";
//do something with ptr
free(ptr);
char *ptr2[10] = {"123", "abc"};
free(ptr2);
Any help would be much appreciated!
If you have a PLAYER **ptr = malloc(10*sizeof(PLAYER *));
That means you have to malloc for every ptr[i] = malloc(sizeof(PLAYER));
Accessing the array at indexes would be ptr[i]->somevalue
NOTE: if you have pointers inside the struct you need to allocate for those as well!!
Freeing your memory would be:
for(int i = 0; i<10;i++){
free(ptr[i]->anyAllocatedPointersInside);
free(ptr[i]);
}
free(ptr);
SPECIFICALLY IN THAT ORDER
If you update the post with the full struct I can update mine to more accurately help you.
When in doubt, think of malloc() allocations in these terms: it allocates raw memory, and it doesn't know anything about your structs!
When you think in these terms, you'll get it right.
Let's try to answer to your questions:
You are basically instancing within the stack a pointer, with any content into it, just as int hello;. That integer can contain anything, because you don't set it as in int hello = 2;. The same thing is happening with your pointers: int * hello; will be a pointer (to an integer) that can contain any address. Hence, if you dereference a pointer like that, your chances to get caught into SIGSEGV are not low.
Then, once you have created those pointers that can be anything, you're assigning their address to the pointer of pointers array you've allocated. Don't do that.
That doesn't work correctly, because if you have an array of pointers to a given type, you can simply increment with += n, the compiler will calculate the appropriate "sizeof(type_you're-pointing_to)" and will add that automatically. This is the main purpose of declaring a pointer to a given type.
You're effectively overwriting other memory.
Brackets are just pointer dereferencing: *ptr+n same as ptr[n].
You need to free each line, and then the array of pointers of pointers.
Basically every pointer you get with malloc(), you have to free it with free(). DO NOT call free() to any other pointers that hasn't been spit out from malloc().
Let me show you some code I have just written to show you better:
#include <stdlib.h>
#include <stdio.h>
#include <string.h> // for memset
#define N_POINTERS 4
#define M_PLAYERS_PER_LINE 3
struct PLAYER
{
int id;
int score;
int age;
};
int
main()
{
// Allocate the array of pointers, big enough to old N pointers.
struct PLAYER ** pointers = malloc(N_POINTERS*sizeof(struct PLAYER*));
// Always better zeroize pointers arrays.
memset(pointers, 0, N_POINTERS*sizeof(struct PLAYER *));
// Allocate each line of M `PLAYER` structs.
// Basically we allocate N chunks of memory big enough to contain M PLAYER structs one next each other.
// What we get is something like this:
//
// pointer pointers PLAYER lines
// of pointers array
// [addrP] -> [addr0] -> [PLAYER0 PLAYER1 PLAYER2] .. M
// [addr1] -> [PLAYER0 PLAYER1 PLAYER2] .. M
// ...N
//
int id = 0;
for (int i = 0; i < N_POINTERS; ++i)
{
pointers[i] = malloc(M_PLAYERS_PER_LINE*sizeof(struct PLAYER));
// Set the data you want to the structs.
for (int k = 0; k < M_PLAYERS_PER_LINE; ++k)
{
pointers[i][k].id = id++;
pointers[i][k].score = 123 + k;
pointers[i][k].age = 33 + i;
}
}
// Print data.
// Here we use a single PLAYER pointer that will
// traverse the entire PLAYER matrix.
struct PLAYER * player;
for (int i = 0; i < N_POINTERS; ++i)
{
for (int k = 0; k < M_PLAYERS_PER_LINE; ++k)
{
// Assign the current PLAYER to our pointer.
player = pointers[i] + k;
// Print PLAYER data, by reading the pointed struct.
printf("Player: #%i age:%i score:%d\n", player->id, player->age, player->score);
}
}
// Deallocate!
for (int i = 0; i < N_POINTERS; ++i)
{
// Deallocate each line chunk.
free(pointers[i]);
}
// Deallocate the array of pointers.
free(pointers);
return 0;
}
As a bonus track, if you need to allocate a matrix of M*N PLAYER structs, you should also look at this code, that will allocate M*N PLAYER structs into one unique memory block, one next each other, which is much more easier to manage, as you can see by the code itself:
#include <stdlib.h>
#include <stdio.h>
#define LINES 4
#define COLUMNS 3
#define GET_ARRAY_POS(lin, col) (col+(lin*COLUMNS))
struct PLAYER
{
int id;
int score;
int age;
};
int
main()
{
// Allocate a *FLAT* array of PLAYER structs, big enough to
// contain N*M PLAYER structs, one next each other.
struct PLAYER * array = malloc(LINES*COLUMNS*sizeof(struct PLAYER));
// Set the data you want to the structs.
int id = 0;
for (int lin = 0; lin < LINES; ++lin)
{
for (int col = 0; col < COLUMNS; ++col)
{
int pos = GET_ARRAY_POS(lin, col);
array[pos].id = id++;
array[pos].score = 123 + col;
array[pos].age = 33 + lin;
}
}
// Print data.
// Here we use a single PLAYER pointer that will
// traverse the entire PLAYER matrix.
for (int i = 0; i < (LINES*COLUMNS); ++i)
{
// Print PLAYER data, by reading the pointed struct.
printf("Player: #%i age:%i score:%d\n", array[i].id, array[i].age, array[i].score);
}
// Deallocate!
free(array);
return 0;
}
Enjoy! ^_^
I get the Error run-time check failure #3, and i have to initialize P and i know why but not how to do it.
Points is supposed to be a variable 2D array like float* points[3] for testing purposes its constant for now.
CVAPI(CvPOSITObject*) lvCreatePOSITObject( float points[5][3], int point_count )
{
CvPoint3D32f* P; //array of structs with int x,y,z
for(int i = 0; i< point_count; i++)
{
P[i].x = points[i][0];
P[i].y = points[i][1];
P[i].z = points[i][2];
}
return cvCreatePOSITObject(P,point_count);
}
I don't know much about OpenCV, but I think you should allocate some memory to store the data.
#include <stdlib.h> // add this to the head of the file to use malloc
CVAPI(CvPOSITObject*) lvCreatePOSITObject( float points[5][3], int point_count )
{
CvPoint3D32f* P; //array of structs with int x,y,z
P = malloc(sizeof(CvPoint3D32f) * point_count); // allocate some memory
for(int i = 0; i< point_count; i++)
{
P[i].x = points[i][0];
P[i].y = points[i][1];
P[i].z = points[i][2];
}
return cvCreatePOSITObject(P,point_count);
}
This code may be bad because this may not free the allocated buffer.
How do you allocate and declare a 3D array of structs in C?
Do you first allocate the array or declare it?
I feel like you have to allocate it first so you can declare it so it is on the heap, but then how do you allocate something that hasn't been made yet?
Also, should you allocate it all at once or element by element?
Also am i putting the structs into the array correctly?
My guess on how to do it would be:
header.h
struct myStruct{
int a;
int b;
};
typedef struct myStruct myStruct_t;
main.c
#include "header.h"
#include <stdio.h>
#include <stdlib.h>
int main(void){
int length=2;
int height=3;
int width =4;
myStruct_t *elements;
struct myStruct arr = (*myStruct_t) calloc(length*height*width, sizeof(myStruct);
//zero based array
arr[length-1][height-1][width-1];
int x=0;
while(x<length){
int y=0;
while(y<height){
int z=0;
while(z<depth){
arr[x][y][z].a=rand();
arr[x][y][z].b=rand();
z++;
}
y++;
}
x++;
}
return 0;
}
The easy way is:
myStruct_t (*arr2)[height][width] = calloc( length * sizeof *arr );
Then your loop can access arr2[x][y][z].a = rand(); and so on. If you're not familiar with this way of calling calloc, see here. As usual with malloc, check arr2 against NULL before proceeding.
The triple-pointer approach is not really a practical solution. If your compiler does not support variably-modified types then the array should be flattened to 1-D.
There are a couple of different ways to do this, depending on what you want. First, you can allocate your array on the stack (in C99 and some compilers) like this:
myStruct_t arr[length][height][depth];
If you want it allocated on the heap, then you can do a single allocation of the appropriate size. You can then either do the index calculation yourself or make a pointer do the work for you (in C99 and some compilers):
void *buf = malloc(length * height * width * sizeof(myStruct_t));
myStruct_t *arr = buf;
myStruct_t (*arr2)[height][width] = buf;
/* TODO: check return of malloc */
...
arr[x * height * width + y * width + z].a = rand(); /* indexing the C89 way */
arr2[x][y][z].b = rand(); /* indexing the C99 way */
Or you can manually allocate the multiple dimensions.
#include <stddef.h>
#include <stdlib.h>
typedef struct myStruct
{
int a, b;
} myStruct_t;
int main()
{
myStruct_t ***arr;
int length = 5000, height = 1000, depth = 20;
int x, y, z;
int ret = 1;
if (NULL == (arr = malloc(length * sizeof(myStruct_t**))))
goto FAIL;
for (x = 0; x < length; ++x)
{
if (NULL == (arr[x] = malloc(height * sizeof(myStruct_t*))))
goto FAIL_X;
for (y = 0; y < height; ++y)
{
if (NULL == (arr[x][y] = malloc(depth * sizeof(myStruct_t))))
goto FAIL_Y;
for (z = 0; z < depth; ++z)
{
arr[x][y][z].a = rand();
arr[x][y][z].b = rand();
}
}
}
/* TODO: rest of program logic */
/* program successfully completed */
ret = 0;
/* reclaim arr */
FAIL_CLEANUP: /* label used by TODO code that fails */
for (x = length - 1; x >= 0; --x)
{
for (y = height - 1; y >= 0; --y)
{
free(arr[x][y]);
FAIL_Y:
;
}
free(arr[x]);
FAIL_X:
;
}
free(arr);
FAIL:
return ret;
}
This last version uses a lot more memory for all the explicit pointers it contains, its memory locality is worse and it's significantly more complex to properly allocate and reclaim. However, it does allow different sizes along your dimensions. For example, the array arr[0][4] can have a different size than arr[0][7] if you ever need that.
If you want to allocate it on the heap, then you probably want the second version with a single allocation and multi-dimension pointer (if available) or do the indexing yourself manually using appropriate math.
I want to create a dynamic array of void*s, each void* will point to 2d int matrix.
All of the matrices have the same number of rows and columns.
How to do this in C?
What do I do after I initialize: void **myArray = NULL;
More specifically, I want to create a function, that takes 2 parameters:
int foo( void* matrix, void** ptrArray)
Where matrix points to 2d int matrix, ptrArray points to an array of void*s, and foo returns the size of ptrArray.
I want, foo to get the 2d int matrix from matrix and make some manipulations on it, like switch some numbers in it. For every change that I make, I want to allocate a new matrix, and save a pointer to it in ptrArray.
Assuming that you allocate your void **twodarray somewhere else and you put NULL in the last+1 element of this array.
I think you want to do something like this;
int function(void **twodarray,void **ptrarray)
{
int i=0
for(i=0;twodarray[i]!=NULL;i++)/*repeat till twodarray points to NULL*/
{
perform some operation on twodarray[i];
ptrarray[i]=twodarray[i];
}
return i+1;/*return length of ptrarray */
}
This way you can tell the no of matrices there are.
But you will have to work out the allocation of void **twodarray by the methods explained in other replies.
You'll have to dynamically allocate each matrix.
For purposes of example I'm going to assume that you are creating your "2d int matrix" as a linear, 16 int array.
#define MATRIX_SIZE 16
int foo(void* matrix, void** ptrArray){
assert(ptrArray == NULL);
int result = 0;
int* first = malloc(MATRIX_SIZE * sizeof(int));
//do stuff to matrix
for(int i = 0; i < MATRIX_SIZE; ++i){
first[i] = matrix[i];
}
ptrArray = malloc((++result) * sizeof(void*));
ptrArray[0] = (void*)first;
int* second = malloc(MATRIX_SIZE * sizeof(int));
//do stuff to matrix
for(int i = 0; i < MATRIX_SIZE; ++i){
second[i] = matrix[i];
}
ptrArray = realloc((++result) * sizeof(void*));
ptrArray[1] = (void*)second;
.
.
.
return result;
}
I am writing a C-program where I need 2D-arrays (dynamically allocated) with negative indices or where the index does not start at zero. So for an array[i][j] the row-index i should take values from e.g. 1 to 3 and the column-index j should take values from e.g. -1 to 9.
For this purpose I created the following program, here the variable columns_start is set to zero, so just the row-index is shifted and this works really fine.
But when I assign other values than zero to the variable columns_start, I get the message (from valgrind) that the command "free(array[i]);" is invalid.
So my questions are:
Why it is invalid to free the memory that I allocated just before?
How do I have to modify my program to shift the column-index?
Thank you for your help.
#include <stdio.h>
#include <stdlib.h>
main()
{
int **array, **array2;
int rows_end, rows_start, columns_end, columns_start, i, j;
rows_start = 1;
rows_end = 3;
columns_start = 0;
columns_end = 9;
array = malloc((rows_end-rows_start+1) * sizeof(int *));
for(i = 0; i <= (rows_end-rows_start); i++) {
array[i] = malloc((columns_end-columns_start+1) * sizeof(int));
}
array2 = array-rows_start; //shifting row-index
for(i = rows_start; i <= rows_end; i++) {
array2[i] = array[i-rows_start]-columns_start; //shifting column-index
}
for(i = rows_start; i <= rows_end; i++) {
for(j = columns_start; j <= columns_end; j++) {
array2[i][j] = i+j; //writing stuff into array
printf("%i %i %d\n",i, j, array2[i][j]);
}
}
for(i = 0; i <= (rows_end-rows_start); i++) {
free(array[i]);
}
free(array);
}
When you shift column indexes, you assign new values to original array of columns: in
array2[i] = array[i-rows_start]-columns_start;
array2[i] and array[i=rows_start] are the same memory cell as array2 is initialized with array-rows_start.
So deallocation of memory requires reverse shift. Try the following:
free(array[i] + columns_start);
IMHO, such modification of array indexes gives no benefit, while complicating program logic and leading to errors. Try to modify indexes on the fly in single loop.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a[] = { -1, 41, 42, 43 };
int *b;//you will always read the data via this pointer
b = &a[1];// 1 is becoming the "zero pivot"
printf("zero: %d\n", b[0]);
printf("-1: %d\n", b[-1]);
return EXIT_SUCCESS;
}
If you don't need just a contiguous block, then you may be better off with hash tables instead.
As far as I can see, your free and malloc looks good. But your shifting doesn't make sense. Why don't you just add an offset in your array instead of using array2:
int maxNegValue = 10;
int myNegValue = -6;
array[x][myNegValue+maxNegValue] = ...;
this way, you're always in the positive range.
For malloc: you acquire (maxNegValue + maxPosValue) * sizeof(...)
Ok I understand now, that you need free(array.. + offset); even using your shifting stuff.. that's probably not what you want. If you don't need a very fast implementation I'd suggest to use a struct containing the offset and an array. Then create a function having this struct and x/y as arguments to allow access to the array.
I don't know why valgrind would complain about that free statement, but there seems to be a lot of pointer juggling going on so it doesn't surprise me that you get this problem in the first place. For instance, one thing which caught my eye is:
array2 = array-rows_start;
This will make array2[0] dereference memory which you didn't allocate. I fear it's just a matter of time until you get the offset calcuations wrong and run into this problem.
One one comment you wrote
but im my program I need a lot of these arrays with all different beginning indices, so I hope to find a more elegant solution instead of defining two offsets for every array.
I think I'd hide all this in a matrix helper struct (+ functions) so that you don't have to clutter your code with all the offsets. Consider this in some matrix.h header:
struct matrix; /* opaque type */
/* Allocates a matrix with the given dimensions, sample invocation might be:
*
* struct matrix *m;
* matrix_alloc( &m, -2, 14, -9, 33 );
*/
void matrix_alloc( struct matrix **m, int minRow, int maxRow, int minCol, int maxCol );
/* Releases resources allocated by the given matrix, e.g.:
*
* struct matrix *m;
* ...
* matrix_free( m );
*/
void matrix_free( struct matrix *m );
/* Get/Set the value of some elment in the matrix; takes logicaly (potentially negative)
* coordinates and translates them to zero-based coordinates internally, e.g.:
*
* struct matrix *m;
* ...
* int val = matrix_get( m, 9, -7 );
*/
int matrix_get( struct matrix *m, int row, int col );
void matrix_set( struct matrix *m, int row, int col, int val );
And here's how an implementation might look like (this would be matrix.c):
struct matrix {
int minRow, maxRow, minCol, maxCol;
int **elem;
};
void matrix_alloc( struct matrix **m, int minCol, int maxCol, int minRow, int maxRow ) {
int numRows = maxRow - minRow;
int numCols = maxCol - minCol;
*m = malloc( sizeof( struct matrix ) );
*elem = malloc( numRows * sizeof( *elem ) );
for ( int i = 0; i < numRows; ++i )
*elem = malloc( numCols * sizeof( int ) );
/* setting other fields of the matrix omitted for brevity */
}
void matrix_free( struct matrix *m ) {
/* omitted for brevity */
}
int matrix_get( struct matrix *m, int col, int row ) {
return m->elem[row - m->minRow][col - m->minCol];
}
void matrix_set( struct matrix *m, int col, int row, int val ) {
m->elem[row - m->minRow][col - m->minCol] = val;
}
This way you only need to get this stuff right once, in a central place. The rest of your program doesn't have to deal with raw arrays but rather the struct matrix type.