I've tried to search out a solution via Google: I couldn't find anything that helped; it even seemed as if I was doing this correctly. The only pages I could find regarding sending my dynamically allocated array through a function dealt with the array being inside a struct, which is scalar of course, so behaves differently. I don't want to use a struct right now -- I'm trying to learn about DAM and working with pointers and functions.
That said, I'm sure it's very elementary, but I'm stuck. The code compiles, but it freezes up when I run the executable. (I'm using minGW gcc, if that matters. And I'm not clear at all, right now, on how to use gdb.)
Here's the code (eventually, I want the entire code to be an ArrayList-like data structure):
#include <stdio.h>
#include <stdlib.h>
void add( int element, int *vector);
void display_vector( int *vector );
void initialize_vector( int *vector );
int elements = 0;
int size = 10;
int main(void)
{
int *vector = 0;
initialize_vector(vector);
add(1, vector);
//add(2, vector);
//add(3, vector);
//add(4, vector);
//add(5, vector);
//add(6, vector);
//add(7, vector);
//add(8, vector);
//add(9, vector);
//add(10, vector);
//add(11, vector);
display_vector(vector);
return 0;
}
void add( int element, int *vector)
{
vector[elements++] = element;
return;
}
void display_vector( int *vector )
{
int i;
for( i = 0; i < elements; i++)
{
printf("%2d\t", vector[i]);
if( (i + 1) % 5 == 0 )
printf("\n");
}
printf("\n");
return;
}
void initialize_vector( int *vector )
{
vector = (int *)malloc(sizeof(int) * size);
}
Edited to make a little bit more clear.
The problem is your init routine is working with a copy of "vector" and is malloc'ing into that copy rather than the original vector pointer. You loose the pointer to the memory block on the return from the initialize.
Change parameter for vector to a handle (pointer to pointer) in this function
void initialize_vector( int **vector )
{
*vector = (int *)malloc(sizeof(int) * size);
}
Then change the call to init to this
initialize_vector(&vector);
I didn't compile this, but it should fix the code.
In C, function arguments are passed by value, which means there is a local copy for every arguments you passed to a function, if you change an argument in a function, you only change the local copy of that argument. So if you want to change the value of an argument in a function, you need to pass its address to that function, derefer that address and assign to the result in that function.
Enough for the theory, here is how to fix your code:
void initialize_vector( int **vector );
initialize_vector(&vector);
void initialize_vector( int **vector )
{
*vector = (int *)malloc(sizeof(int) * size);
}
In addition of other replies, I would suggest another approach.
Assuming at least C99 compliant compiler, I would rather suggest to keep the allocated size in a member of a structure ending with a flexible array member (see also this) like:
typedef struct vector_st {
unsigned count; // used length
unsigned size; // allocated size, always >= length
int vectarr[];
} Vector;
Then you would construct such a vector with
Vector* make_vector (unsigned size) {
Vector* v = malloc(sizeof(Vector)+size*sizeof(int));
if (!v) { perror("malloc vector"); exit (EXIT_FAILURE); };
memset (v->vectarr, 0, size*sizeof(int));
v->count = 0;
v->size = size;
}
To add an element into a vector, returning the original vector or a grown one:
Vector* append_vector (Vector*vec, int elem) {
assert (vec != NULL);
unsigned oldcount = vec->count;
if (oldcount < vec->size) {
vec->vectarr[vec->count++] = elem;
return vec;
} else {
unsigned newsize = ((4*oldcount/3)|7) + 1;
Vector* oldvec = vec;
vec = malloc(sizeof(Vector)+newsize*sizeof(int));
if (!vec) { perror("vector grow"); exit(EXIT_FAILURE); };
memcpy (vec->vectarr, oldvec->vectarr, oldcount*sizeof(int));
memset (vec->vectarr + oldcount, 0,
(newsize-oldcount) * sizeof(int));
vec->vectarr[oldcount] = elem;
vec->count = oldcount+1;
vec->size = newsize;
free (oldvec);
return vec;
}
}
and you could code:
Vector* myvec = make_vector(100);
myvec = append_vector(myvec, 35);
myvec = append_vector(myvec, 17);
for (int i=0; i<150; i++)
myvec = append_vector(myvec, i*2);
To release such a vector, just use free(myvec);
If you really don't want to use any struct you should keep in separate variables the used length of your vector, the allocated size of your vector, the pointer to your dynamically allocated array:
unsigned used_count; // useful "length"
unsigned allocated_size; // allocated size, always not less than used_count
int *dynamic_array; // the pointer to the dynamically allocated array
If you want to be able to manage several vectors, then either pack together the above useful length, allocated size and dynamic array into some struct dynamic_array_st (whose pointer you would pass to appropriate routines like make_dynamic_vector(struct dynamic_array_st*), append_dynamic_vector(struct dynamic_array_st*, int), etc ....) or else pass them as three separate formals to similar routines, and then you'll need to pass their address because the routines would change them, e.g. create_dynamic_vector(unsigned *countptr, unsigned *sizeptr, int**vectarrptr) that you would invoke as create_dynamic_vector(&mycount, &mysize, &myvectarr); etc.
I do think that a flexible array member is still the cleanest approach.
Related
I have a program in C, in which I initialize multiple number of arrays each with a bunch of lines. However, i'd like to avoid that since it increases the length of my main function. For example I have this;
int * pickup_Ind;
double *pickup_Val;
pickup_Ind = (int *) malloc(sizeof(int) * (size1));
pickup_Val = (double *) malloc(sizeof(double) * (size1));
int * lInd;
double *lVal;
lInd = (int *) malloc(sizeof(int) * size2);
lVal = (double *) malloc(sizeof(double) * size2);
int * simul_Ind;
double *simul_Val;
simul_Ind = (int *) malloc(sizeof(int) * (size3));
simul_Val = (double *) malloc(sizeof(double) * (size3));
I know I can reduce the number of lines by for example writing as:
int * pickup_Ind = (int *) malloc(sizeof(int) * (size1));
But still i will need to do this for every array. How to write this in a compact form with a function (which i will store in a header file), and then call this function from main. Not to mention i do not want to declare them as global variables, but to be able to use them in main. I tried the function below.
void initialize_bounds(int *arr1,int size1)
{
arr1= (int *) malloc(sizeof(int) * (size1));
for(int i=0;i<size1;i++)
arr1[i]=i;
}
But if i call this function via the following in main, i get error "Varuable test being used without initialized"
int* test;
initialize_bounds(test);
So to sum up, if i could write something like this, my problem is solved:
int *pickup_Ind,*pickup_Val,*lind,*lval;
int size1,size2;
initalize_bounds(pickup_Ind,pickup_Val,size1,size2);
You could write a function
void initialize_bounds(int **ind, double **val, int size) {
*ind = malloc(sizeof (**ind)*size);
for (int i = 0; i < size; i++) {
(*ind)[i] = i;
}
*val = malloc(sizeof (**val)*size);
}
and call it like
int * pickup_Ind;
double *pickup_Val;
initialize_bounds(&pickup_Ind, &pickup_Val, size1);
to initialize both arrays in one line. You still have to place one call to it per array-pair, however.
In the C language, arguments are passed to functions by value - so, actually, a copy is made and the original variable (in the calling code) cannot be changed. So, if you want a function to modify (say) an int argument, you pass it a pointer to that int.
Likewise, if you want a function to modify a pointer, you have to pass a pointer to that pointer.
So, in the case of the initialize_bounds function you have shown, you would need this:
void initialize_bounds(int** arr1,int size1) // 1st arg is a pointer to the pointer!
{
*arr1 = (int *) malloc(sizeof(int) * (size1)); // De-reference our `arr1` pointer
for(int i=0;i<size1;i++)
(*arr1)[i]=i;
}
Then, you can use this to initialize a pointer in your main function with a call like this:
int* test;
initialize_bounds(&test); // We need to pass the ADDRESS of the pointer we want to modify!
You can write a function that returns a freshly allocated and initialized array.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
/* Header file */
int* AllocateArray(size_t size);
void DeallocateArray(int *array);
int main(void) {
const size_t size = 10;
int *const array = AllocateArray(size);
for (size_t i = 0; i < size; ++i) {
printf("%d ", array[i]);
}
printf("\n");
DeallocateArray(array);
return 0;
}
/* Implementation */
int* AllocateArray(size_t size) {
int *const array = malloc(size * sizeof(int));
if (array == NULL) {
// Allocation failed, handle it...
}
for (size_t i = 0; i < size; ++i) {
array[i] = i;
}
return array;
}
void DeallocateArray(int *array) {
if (array == NULL) {
return;
}
free(array);
}
I'd use something higher level, e.g. stretchy buffers. See this video for a live coding session that implements those - props to Per Vognsen for making this code, and for placing into public domain (i.e. completely free to use for any purpose, but I'm not a lawyer, so take anything I say with caution :).
You'd want to include bitwise/ion/common.c in your source file, and then the array allocation becomes simple. Stretchy buffers are perhaps the closest you get to the convenience of C++'s std::vector in C. They offer an API that doesn't feel like a C++ API transcribed in C - it is at the correct level, and lets you use plain pointers in a very sensible way (e.g. a buf_len of a NULL pointer is zero, not a crash, buf_push(mybuf, element) appends an element to the array and extends it if necessary, etc.
#include <assert.h>
#include <string.h>
#include <stdlib.h>
// note that common.c includes nothing, so you have to set it up
#include "common.c"
#define buf_resize(b, n) ((n) <= buf_len(b) ? (b) : (((b) = buf__grow((b), (n), sizeof(*(b)), 0)), ((b) ? buf__hdr((b))->len = (n) : 0), (b)))
typedef struct {
int * pickup_Ind;
double *pickup_Val;
int * lInd;
double *lVal;
int * simul_Ind;
double *simul_Val;
} Data;
enum {
size1 = ...,
size2 = ...,
size3 = ...
}
Data make_Data(void) {
Data d;
memset(&d, 0, sizeof(d));
assert(buf_len(d->pickup_Ind) == 0);
buf_resize(d.pickup_Ind, size1);
buf_resize(d.pickup_Val, size1);
buf_resize(d.lInd, size2);
buf_resize(d.lVal, size2);
buf_resize(d.simul_Ind, size3);
buf_resize(d.simul_Val, size3);
}
int main(int argc, char **argv) {
Data d = make_Data();
assert(buf_len(d.pickup_Ind) == size1);
d.pickup_Ind[0] = 10;
assert(buf_len(d.pickup_Ind) == size1);
buf_push(d.pickup_Ind, 11);
assert(buf_len(d.pickup_Ind) == size1 + 1);
}
If you're building up the arrays by adding elements to them one-by-one, it'll make sense to reserve the capacity for the expected size of the array via buf_fit (it only reserves the memory but the buffer retains its length (e.g. zero)). The capacity reservation is entirely optional, though. It's there to prevent reallocation of the arrays while you add elements to them.
Thus:
Data make_Data(void) {
Data d;
memset(&d, 0, sizeof(d));
assert(buf_len(d->pickup_Ind) == 0);
buf_fit(d.pickup_Ind, size1);
buf_fit(d.pickup_Val, size1);
buf_fit(d.lInd, size2);
buf_fit(d.lVal, size2);
buf_fit(d.simul_Ind, size3);
buf_fit(d.simul_Val, size3);
}
int main(int argc, char **argv) {
Data d = make_Data();
assert(buf_len(d.pickup_Ind) == 0); // zero length: no data in the array (yet!)
assert(buf_cap(d.pickup_Ind) >= size1); // but it has the capacity we need
buf_push(d.pickup_Ind, 10);
buf_push(d.pickup_Ind, 11);
assert(buf_len(d.pickup_ind) == 2);
}
If you'll want to use stretchy buffers in multiple source files, you'll run afoul of the one declaration rule (ODR). Thus, you'll need to factor out macro definitions and function declarations out of common.c and into common.h.
If the Data is only allocated once, there's no need to free it prior to exiting the program: the operating system already does it for you. Otherwise, you may wish to add a function to do this job:
void free_Data(Data *d) {
buf_free(d.pickup_Ind);
buf_free(d.pickup_Val);
buf_free(d.lInd);
buf_free(d.lVal);
buf_free(d.simul_Ind);
buf_free(d.simul_Val);
assert(buf_len(d.pickup_Ind) == 0);
}
I'm new to programming and to C, and I just learned about structs. I'm trying to use them to make an array which can change size as required (so, if the array gets full, it creates a new array double the size, copies the old array into the new one and deletes the old one). All I've done so far is create the struct and the functions for setting it up, and already I'm having problems. The main problem is that, sometimes when I run it it does exactly what I expect it to, which is create the struct, return a pointer to said struct, and then print all elements of the contained array. Other times when I run it, it does nothing at all! I don't get how it can work sometimes, and sometimes not! Obviously i'm doing something really wrong, but I can't work out what. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int cap;
int used;
void (*cpy) (int *, const int *, int);
//void (*append) (int);
int array[];
} dynArray;
dynArray * new_dynArray(int *, int);
void copy(int *, const int *, int);
int main(void) {
int start_arr[] = {1,2,3,4,5,6};
// create new dynArray, pass start array and number of elemnts
dynArray *arr = new_dynArray(start_arr, \
sizeof(start_arr) / sizeof(start_arr[0]));
// print all elements of dynArray
for (int i=0; i<(arr->used); i++) {
printf("%d, %d\n", arr->array[i], i);
}
free(arr);
return 0;
}
dynArray * new_dynArray(int init_arr[], int size) {
//printf("%d", size);
// if number of elements >= 4 then dynArray size is double, else 8
int init_cap = (size >= 4) ? 2 * size : 8;
// create pointer with enough space for struct and the actual array
dynArray *arr = (dynArray *) malloc(sizeof(dynArray) + init_cap );
arr->cap = init_cap;
arr->used = size;
// assign address of funciton copy to arr->cpy
arr->cpy = copy;
// call the function, to copy init_arr to arr->array
arr->cpy(arr->array, init_arr, size);
return arr;
}
void copy(int dest[], const int src[], int src_size) {
// just copy initial array to new array
int i;
memcpy(dest, src, src_size*sizeof(int));
/*
for (i=0; i<src_size; i++) {
dest[i] = src[i];
printf("%d\n", dest[i]);
}*/
}
So I call init_dynArray, sending a normal array and the number of elements in the array. init_dynArray uses malloc to create space in memory for the struct + the inintal size of the array, set up everything in the struct and copy the array, and then return a pointer to it. I don't get how it can only work some of the time. Hope yuo guys can help, thanks!
The problem in your code is on this line:
dynArray *arr = (dynArray *) malloc(sizeof(dynArray) + init_cap );
You need to multiply init_cap by sizeof(int)
dynArray *arr = (dynArray *) malloc(sizeof(dynArray) + sizeof(int)*init_cap );
You should also use size_t for the init_cap's type.
Note: Storing a pointer to the copying function inside the struct would be useful if your dynamic array consisted of opaque elements that require non-trivial copying. Since copying ints can be accomplished with a simple memcpy, there is no need to store a function pointer in dynArray.
I'm trying to refactor my code to make it better/more readable so I'm trying change a 2-D variable array allocation as follows
// OLD CODE
int **map;
map = calloc(number, sizeof(int *));
if (!(map)) {
free(map);
return 1;
}
for (int i = 0; i < number; i++) {
map[i] = calloc(number, sizeof(int));
if (!(map[i])) {
while (--i >= 0) {
free(map[i]);
}
free(map);
return 1;
}
}
// NEW CODE
int (*map)[number] = malloc(sizeof (int[number][number]));
if (!(map)){
free(map);
return 1;
}
The problem is that all my functions that use map take int **map and by changing the declaration of map like i did the IDE tells me incorrect type int[]* instead of int**
What should i use instead of int**? Using int[]* map in the function declaration tells me can't resolve variable map
Turns out the below code is not a C99 alternative #M.M, but a GCC extension.
Undocumented GCC Extension: VLA in struct
As a C99 GCC extension alternative to int (*map)[number] = malloc(sizeof (int[number][number])); for code simplification and maintain compatibility with existing function set, allocate all the memory needed with 1 *alloc() call.
This does require that when code is done with the map, all the memory is free'd with one free(map). Further, individual rows of map[] can no longer be re-allocated, but can be swapped within the map[].
int **map_allocate(size_t row, size_t column) {
struct {
int *ip[row]; // Array of pointers, followed by a ...
int i[row][column]; // 2D array of int
} *u;
u = calloc(1, sizeof *u);
if (u == NULL) {
return NULL;
}
for (size_t i = 0; i<row; i++) {
u->ip[i] = u->i[row];
}
return &u->ip[0];
}
Note: no casting and field i[][] is properly aligned.
To use one allocation with standard code, unlike the other answer, is a bit trickier as one needs to insure that a combined memory allocation of pointers and int needs to meet alignment concerns in the unusual case of int alignment requirements exceed pointer alignment ones. This is more easily shown with long long as below.
If this makes "code easier to read" is left to OP's judgment.
#include <stdlib.h>
#include <stdio.h>
long long **map_allocate_ll(size_t row, size_t column) {
long long **map;
long long *ints;
size_t pointers_sz = sizeof *map * row;
// extend pointer size to `*ints` boundary
pointers_sz = (pointers_sz + sizeof *ints - 1)/sizeof *ints * sizeof *ints;
size_t ints_sz = sizeof *ints * row * column;
printf("psize %zu, isize %zu\n", pointers_sz, ints_sz);
map = calloc(1, pointers_sz + ints_sz);
if (map == NULL) {
return NULL;
}
ints = (void*) ((char*) map + pointers_sz);
printf("map %p\n", (void *) map);
for (size_t i = 0; i<row; i++) {
map[i] = &ints[i * column];
printf("map[%zu] %p\n", i, (void *) map[i]);
}
return map;
}
int main() {
free(map_allocate_ll(5,3));
}
Sample output
psize 24, isize 120
map 0x80081868
map[0] 0x80081880
map[1] 0x80081898
map[2] 0x800818b0
map[3] 0x800818c8
map[4] 0x800818e0
In a number of vector implementations which I've seen, the following definition of vector structure is used:
struct vector {
void **data;
int size;
int count;
};
Why do we need pointer-to-pointer member here?
Because it can be a vector of pointer elements which can have any type (including pointers) since void * is convertible to any pointer type in c1. Also, elements will be separated by the size of a pointer making it simpler to work with.
You can then get the actual value by dereferencing the void * pointer to the element after casting to the appropriate pointer type or simply getting a pointer if the elements are pointers.
Sample implementation (far from complete of course2)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct vector
{
void **data;
size_t count;
size_t size;
};
void
vector_new(struct vector *vector, size_t size, size_t nmemb)
{
vector->data = NULL;
vector->count = 0;
vector->size = size;
}
void
vector_push_back(struct vector *vector, void *value)
{
unsigned char **data;
data = realloc(vector->data, sizeof(*data) * (vector->count + 1));
if (data == NULL)
return; // Probably return an error indicator
vector->data = (void *) data;
data[vector->count] = malloc(vector->size);
if (data[vector->count] == NULL)
return; // Probably return an error indicator
memcpy(data[vector->count], value, vector->size);
vector->count++;
}
void *
vector_get(struct vector *vector, size_t index)
{
return (unsigned char *) vector->data[index];
}
int
main(void)
{
struct vector vector;
vector_new(&vector, sizeof(float), 100);
for (int i = 0 ; i < 10 ; ++i)
{
float value;
value = (float) rand() / RAND_MAX;
fprintf(stdout, "vector[%d] %f\n", i, value);
vector_push_back(&vector, &value);
}
fprintf(stdout, "Read them to check!\n");
for (int i = 0 ; i < 10 ; ++i)
{
float value;
value = *(float *) vector_get(&vector, i);
fprintf(stdout, "vector[%d] %f\n", i, value);
}
return 0;
}
1 This kind of construction is generally a bad design choice since it's quite hard to maintain and it's harder to write accessor functions. Nevertheless there are geniune use cases for it of course. The c language should not be used for generic typing, trying to enforce that has usually less benefits than problems.
2It lacks a free/destroy function for example.
See a nice recap of functionality expected of a vector at vector (the link goes to vector in C++, but the information on their functionality applies to vector in general, in C or C++ or any other language for that matter).
Salient points are abstracted below. The functionality gives you clues about why the data structure is the way it is.
Vectors are sequence containers representing arrays that can change in
size.
Just like arrays ... their elements can also be accessed using offsets
on regular pointers to its elements ... But unlike arrays, their size
can change dynamically ...
... vector containers may allocate some extra storage to accommodate
for possible growth ... and thus, vectors do not reallocate each time
an element is added to the container.
struct vector {
void **data; // needs to act like an array of pointers i.e. void *data[]
int size; // actual memory allocated may be in access of count
int count; // current count of elements in data
};
It's quite common. You can treat it as:
char *data[size];
So each element is a string, or any storage type which size is unknown until runtime. For exampleint i=123;
data=malloc(sizeof(int));
memcpy(data, &i, sizeof(i));
How to return 1000 variables from a function in C?
This is an interview question asked which I was unable to answer.
I guess with the help of pointers we can do that. I am new to pointers and C can anyone give me solution to solve this problem either using pointers or different approach?
Pack them all in a structure and return the structure.
struct YourStructure
{
int a1;
int b2;
int z1000;
};
YouStructure doSomething();
If it's 1000 times the same type (e.g. int's):
void myfunc(int** out){
int i = 0;
*out = malloc(1000*sizeof(int));
for(i = 0; i < 1000; i++){
(*out)[i] = i;
}
}
This function allocates memory for 1000 integers (an array of integers) and fills the array.
The function would be called that way:
int* outArr = 0;
myfunc(&outArr);
The memory held by outArr must be freed after use:
free(outArr);
See it running on ideone: http://ideone.com/u8NX5
Alternate solution: instead of having myfunc allocate the memory for the integer array, let the caller do the work and pass the array size into the function:
void myfunc2(int* out, int len){
int i = 0;
for(i = 0; i < len; i++){
out[i] = i;
}
}
Then, it's called that way:
int* outArr = malloc(1000*sizeof(int));
myfunc2(outArr, 1000);
Again, the memory of outArr must be freed by the caller.
Third approach: static memory. Call myfunc2 with static memory:
int outArr[1000];
myfunc2(outArr, 1000);
In that case, no memory has to be allocated or freed.
Array Pointer approach:
int * output(int input)
{
int *temp=malloc(sizeof(int)*1000);
// do your work with 1000 integers
//...
//...
//...
//ok. finished work with these integers
return temp;
}
Struct pointer approach:
struct my_struct
{
int a;
int b;
double x;
...
//1000 different things here
struct another_struct;
}parameter;
my_struct * output(my_struct what_ever_input_is)
{
my_struct *temp=malloc(sizeof(my_struct));
//...
//...
return temp;
}
This is how you do it in C.
void func (Type* ptr);
/*
Function documentation.
Bla bla bla...
Parameters
ptr Points to a variable of 'Type' allocated by the caller.
It will contain the result of...
*/
If your intention wasn't to return anything through "ptr", you would have written
void func (const Type* ptr);
instead.