I've problem using void *. How should I do to use this clean_buffer function for int and float arrays.
void clean_buffer( void *ptr, int n)
{
for( int i = 0; i < n; i++)
ptr[i]=0;
}
int main(void)
{
float *pf;
int *pi;
pf = (float *) malloc(10*sizeof(float));
pi = (int *)malloc(10*sizeof(int));
clean_buffer( (float *)pf, 10);
clean_buffer( (int *)pi, 10);
return 0;
}
void is a non value you cannot use *((void*) x) = v; and to use a cast to use a pointer to an other type is dangerous because the size may not be the same
But, in your case you set to 0, so you can use memset or replace the malloc my calloc and it is useless to have clean_buffer :
int main(void)
{
float *pf;
int *pi;
pf = calloc(10, sizeof(float));
pi = calloc(10, sizeof(int));
return 0;
}
Type void has no size. Therefore you cannot use void * to clear an array.
You can not dereference that type for the same reason.
You must cast to a pointer with specific type:
void clean_buffer(void *ptr, size_t n)
{
unsigned char *my_ptr = ptr;
for (int i = 0; i < n; i++)
my_ptr[i]=0;
}
You need to take care that the size passed to your function cannot be the number or arrays because the compiler cannot do pointer arithmetics with void* pointers.
And for sizes you should use size_t
Instead you have to pass the size of the array in bytes:
int main(void)
{
float *pf;
int *pi;
pf = malloc(10*sizeof(float));
pi = malloc(10*sizeof(int));
clean_buffer( pf, 10*sizeof(float));
clean_buffer( pi, 10*sizeof(int));
return 0;
}
Or you need to pass any other information that can be used to determine type and/or size of the data.
Also:
Casting the return value of malloc is not needed in C.
Casting the parameters of clean_buffer to a type that the variable already has, is useless. The pointer type is converted to void * anyway as this is what the function expects.
Note:
Other answers and comments mention that you could simply pass the pointer to memset or use calloc etc.
This might be true for this very specific case but if you want to do anything else than simply zeroing the memory, the same aspects regarding void * pointers apply as I have shown here. And in those cases memset or calloc are of no help.
I've problem using void *. How should I do to use this clean_buffer function for int and float arrays (?)
Others have mentioned useful things like the need to sizeof to find the size, cast not needed and alternatives to use calloc() for a zero initialized memory allocation.
To add:
sizeof *object_pointer
Use sizeof *object_pointer to find the size. It is less error prone, easier to review and maintain than coding in the type.
// clean_buffer( (float *)pf, 10);
// clean_buffer( (int *)pi, 10);
// cast not needed
clean_buffer(pf, sizeof *pf * 10); // No need to mention type!
clean_buffer(pi, sizeof *pi * 10);
volatile
Scrubbing memory after its final use is prone to being optimized out and then a good reason to not use memset() when memory security is of concern. Instead use volatile to prevent clean_buffer() from itself being optimized out.
void clean_buffer(void *ptr, size_t n) {
volatile unsigned char *vuc = ptr;
for(size_t i = 0; i < n; i++)
vuc[i]=0;
}
}
You cast ptr to the appropriate type so it can dereferenced to clear what it points to; something you know points to a type that you want to clear i items of.
void clean_buffer( void *ptr, int n)
This function demands a void * as a parameter.
clean_buffer( (float *)pf, 10);
Here you are casting to a float pointer. So this a different type as demanded
Also void has no size, so you cant really use [] on ptr
malloc itself returns a void pointer as it doesn't really know for which type you are allocating memory. So, you need to use the same size which you pass to malloc for clearing the buffer also.
You can use memset and pass the size of the entire buffer to clear it without having to worry about it's type.
void clean_buffer( void *ptr, size_t n)
{
memset(ptr, 0, n)
}
int main(void)
{
float *pf;
int *pi;
pf = (float *) malloc(10*sizeof(float));
pi = (int *)malloc(10*sizeof(int));
clean_buffer(pf, 10*sizeof(float));
clean_buffer(pi, 10*sizeof(int));
return 0;
}
Additionally, as others have suggested, you can use calloc if it suits you.
Related
So when I pass a data type like a struct to assign some memory to it I find that the pointer doesn't change within the main scope. This further becomes a problem when I try to free the memory but obviously if its using the original pointer it will be pointing at the stack address.
void allocate(int *value){
value = malloc(10 * sizeof(int));
}
int main(){
int val2;
allocate(&val2);
free(&val2);
return 0;
}
I can fix this by using a double pointer to be passed into the allocate function but some course work I'm doing requires to only pass a pointer and I cant get it to update the pointer when it returns to main. I have looked around for a while but cant find a straight forward answer, I feel like my coursework is wrong but that might be my lack of understanding.
The requirement to "only pass a pointer" seems contrived, and you could argue that a pointer to pointer (not a "double pointer") is a pointer, but perhaps you could use void * to punch a hole in the type system. Or use a struct:
#include <stdlib.h>
#include <stdio.h>
struct intbuffer {
int *d;
size_t cap;
};
void *
xmalloc(size_t s)
{
void *r = malloc(s);
if( r == NULL ){
perror("malloc");
exit(1);
}
return r;
}
void
allocate(void *p, size_t s)
{
*(int **)p = xmalloc(s * sizeof(int));
}
void
allocate2(struct intbuffer *p)
{
p->d = xmalloc(p->cap * sizeof *p->d);
}
int
main(void)
{
int *val2;
struct intbuffer v;
allocate(&val2, 10);
free(val2);
v.cap = 10; /* Horrible api!! */
allocate2(&v);
free(v.d);
return 0;
}
Note that setting the capacity in the struct prior to making the call to allocate is a violation of many principles of software design, but this whole thing is absurdly contrived due to the bizarre artificial limitations.
There are not enough *'s in each place, but you will have to figure out what that means.
void allocate(int** value){
*value = malloc(10 * sizeof(int));
}
int main(){
int* val2;
allocate(&val2);
free(val2);
return 0;
}
In my notes the following code is provided as an example of a programm to allocate and deallocate
memory that doesn't work because the vett variable in the allocate function is local. The function is fixed by using a double pointer and doing the changes in the commented code
void allocate(double *vett, int n) //void allocate(double **vett, int n);
{ printf("vett=%p\n",vett); // printf("vett=%p\n",*vett);
vett = (double*)calloc(n,sizeof(double)); //*vett = (double*)calloc(n,sizeof(double));
printf("vett=%p\n",vett); // printf("vett=%p\n",*vett);
}
void freeit(double *vett) { free(vett); }
int main(int argc,char **argv)
{
double *v=NULL;
int i, size=atoi(argv[1]);
allocate(v,size); // allocate(&v,size);
printf("v=%p\n",v); //printf("v=%p, &v=%p\n",v,&v);
for(i=0;i<size;i++)
v[i]=i;
for(i=0;i<size;i++)
printf("v[%d]=%f\n",i,v[i]);
freeit(v);
return 0;
}
My question is do we really need a double pointer to fix the code? I came up with the following solution:
void* allocate(double *vett, int n) // I changed here
{ printf("vett=%p\n",vett);
vett = (double*)calloc(n,sizeof(double));
printf("vett=%p\n",vett);
return vett; // I added this
}
void freeit(double *vett) { free(vett); }
int main(int argc,char **argv)
{
double *v=NULL;
int i, size=atoi(argv[1]);
v=allocate(v,size); // I changed here
printf("v=%p\n",v);
for(i=0;i<size;i++)
v[i]=i;
for(i=0;i<size;i++)
printf("v[%d]=%f\n",i,v[i]);
freeit(v);
return 0;
}
Is my solution ok? If it is, is any of the solutions preferable over the other?
Additionaly in the following site https://aticleworld.com/dangling-pointer-and-memory-leak/ I found the following functions, but I don't think the Memory_Allocate function is correct, since it returns a local variable ( pvHandle). Am I right?
static unsigned int Allocate_Counter = 0;
static unsigned int Deallocate_Counter = 0;
void *Memory_Allocate (size_t size)
{
void *pvHandle = NULL;
pvHandle = malloc(size);
if (NULL != pvHandle)
{
++Allocate_Counter;
}
else
{
//Log error
}
return (pvHandle);
}
void Memory_Deallocate (void *pvHandle)
{
if(pvHandle != NULL)
{
free(pvHandle);
++Deallocate_Counter;
}
}
int Check_Memory_Leak(void)
{
int iRet = 0;
if (Allocate_Counter != Deallocate_Counter)
{
//Log error
iRet = Memory_Leak_Exception;
}
else
{
iRet = OK;
}
return iRet;
}
Your second example is correct, in the case you return back a pointer, that pointer is the one received from calloc(). And in that case there's no need for the double pointer. In the first case, without returning the pointer with return, the problem is that the pointer you pass to the function is copied in, and the copy can be modified inside the function, but that copy is different than the value of the variable you got it from.
Now two hints:
I have told you this in a comment to the question but: NEVER cast the result of malloc() and friends. You hide several possible errors if you cast the value returned: if you forget to #include <stdlib.h> the compiler will assume the function returns an int (wrongly, a pointer and a int are not the same size in 64bit architectures, and getting a 32 bit value will truncate your data to 32 bits, to later extend it to 64) and will generate code for getting an int that will be converted to a pointer (because of the cast, wrong again) with no warning from the compiler (because you have said with the cast don't worry, I know what I'm doing)
You return a void * from your function, which returns the value of a variable that is of type double *, and do so without a cast, that illustrates how the void * can be automatically converted by the compiler, so making the cast from malloc() totally unnecessary. But why don't return instead a double *, as you have already made the effort to convert a void * into a double *, just to convert it back to void *. If you want a wrapper function to return arrays of doubles, then return a double * in the function, and then you'll avoid the type conversion you do in the return statement, just to convert it again back to double * (which I guess this is what you want).
This applied to your code results in these comments:
/* return void *? Why did you convert it to double *? */
void* allocate(double *vett, int n)
/* why pass a pointer if you are not using the value inside the function body? */
{ printf("vett=%p\n",vett); /* well you print it :$ */
/* don't cast the automatic conversion, let the compiler do its work */
vett = (double*)calloc(n,sizeof(double));
printf("vett=%p\n",vett);
return vett; /* the double * stored in vett is converted to a void * to return it */
}
void freeit(double *vett) { free(vett); }
int main(int argc,char **argv)
{
double *v=NULL;
int i, size=atoi(argv[1]);
v=allocate(v,size); /* and you convert it again to double * here */
printf("v=%p\n",v);
...
so you get a void *, cast it to double * to be stored in a pointer variable, convert it to void * again to return the value to main and convert it again automatically to store it in main's v variable. My conclusion from this sample is that you never cast the value of malloc, and you should use the type void * as low as possible. The standard library functions do it for reasons out of scope, and trying to emulate them is something you can try, but when you have a better understanding of pointers. Until then, better never use void * pointers. A general principle is that you should the proper types, you never had to cast them. Casting should not be necessary (and it's almost never done in well written code) so better avoid casting as much as you can. The 80% of the errors come from bad casts, and the other 20% come from improperly defined types. C is already a language too lazy in type management, don't make it more by overusing of casts.
In my opinion, your code should be:
double *allocate_doubles(int n)
{
/* automatic conversion is done here only */
double *vett = calloc(n, sizeof(double));
printf("vett=%p\n", vett);
/* no conversion as vett is already of the function return type */
return vett;
}
void freeit(double *vett)
{
free(vett);
}
int main(int argc, char **argv)
{
double *v = NULL; /* use spaces, for readability */
int i, /* this is more readable */
size = atoi(argv[1]);
/* and no conversion because both, allocate and v are the same type */
v = allocate(v, size);
printf("v=%p\n", v);
for(i = 0; i < size; i++)
v[i] = i;
for(i = 0; i < size; i++)
printf("v[%d]=%f\n", i, v[i]);
freeit(v);
return 0;
}
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);
}
So i wanted to create a swap function that will allocation size of character array dynamically. Is it possible? Is it recommended?
My code that shows errors.
void swap(void * vp1, void * vp2, int size)
{
char buffer[size]; //size must have a constant value is the error i am getting.
memcpy(buffer, vp1, size);
memcpy(vp1, vp2, size);
memcpy(vp2, buffer, size);
}
char buffer[size];
An array whose size is not known at compile time is known as a variable length array. These are C-only features. Since this is giving an error, you are using a C++ compiler. You must change size so that it will be known at compile time.
The following are valid C++ array definitions
#define NUM 8
int a[16];
int a[NUM];
This is ill-formed:
int n;
printf("What is your age?\n");
scanf("%d", &n);
int a[n];
because n depends on what the user types.
The solution is to cast the void pointer arguments into pointers to unsigned char, and then manipulate the unsigned char *
void swap(void *a, void *b, size_t n)
{
unsigned char *p = (unsigned char *) a,
*q = (unsigned char *) b,
tmp;
for (size_t i = 0; i < n; ++i) {
tmp = p[i];
p[i] = q[i];
q[i] = tmp;
}
}
But since you're using C++, it is a better idea to use templates.
Unfortunately MSVC is the only major C compiler that doesn't support your code. To support all compilers you can write:
void swap(void * vp1, void * vp2, int size)
{
char *buffer = malloc(size);
if ( buffer )
{
memcpy(buffer, vp1, size);
memcpy(vp1, vp2, size);
memcpy(vp2, buffer, size);
free(buffer);
}
}
Note: This way is simple in code but there may be more efficient options, especially if you are typically only swapping small buffers.
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.