简体   繁体   中英

Variable array size in c

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 free s 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM