changing fixed size array to dynamic in C - c

I have an char array of fixed size in C application. I am passing that array to some function and from there I am passing it to multiple functions. So that the array gets filled in some of the functions based on some condition. Since I am sending a fixed size array I am facing problem when I copy data to it if the size is more than the array size. I know that I have to make that char array dynamic but as I said that array gets filled in multiple functions and size will be different. So do I need to dynamically allocate the array wherever it gets filled? Consider the array gets filled in 30+ different functions. Or is there a way to do a minimal modification?

As your question title says C, IMO the best approach will be to decalre a pointer of that particular variable type in your main() function, pass the address of that pointer [essencially a double-pointer] to other functions and allocate memory dynamically.
You can keep on passing the pointer to all other functions. Inside every called functions, measure the amount of memory required to put the data [from that particular function] and use realloc() to increase the available memory.
As mentioned by UncleO, the required pointer should be the pointer to array [i.e, a double pointer]
EDIT
For the very first time allocating memory to that pointer, you can use malloc() or calloc().
From next time onwards, to extend [resize] the amount of memory, you need to use realloc()

You don't pass an array to a function in C, although it appears that way. What gets passed is a pointer to the first element of the array. The pointer is passed by value. That is, the value of the pointer (the memory location) is copied into a local variable. The contents of the array can be changed using this local variable.
If you use malloc() or realloc() with this local variable, then the pointer that was "passed in" won't be affected. realloc() may resize the memory, but it can also free that memory and allocate some new memory to the local variable.
If you want to change the array pointer, then you should pass in a pointer to the pointer. The thing the pointer points to is what is changed. This is a bit more cumbersome. But this way you can allocate more memory is needed.
#include <stdlib.h>
char* arr;
void changeit(char** arrptr)
{
*arrptr = realloc(*arrptr, 20*sizeof(char));
}
void main (void)
{
arr = malloc(10*sizeof(char));
changeit(&arr);
}

To function that do not alter the array, pass the array address and size.
int foo1(const char *array, size_t size, ...)
To each function that does not change the array size, pass array address and array size
int foo2(char *array, size_t size, ...)
To functions that may alter the array size, pass the address of the address of the array and the address of the size.
int foo3(char **array, size_t *size, ...)
Code could put these two variables together
typedef struct {
size_t size;
char array;
} YetAnotherArrayType;

Chux,
There's a little typo at then end of your post. I think you mean:
typedef struct {
size_t size;
char* array;
} YetAnotherArrayType;
You didn't make array a pointer type.
If the poster is handcrafting a container, the classic solution is to track both a size and a capacity.
In that model you allocate the array to some initial a capacity and set size to 0. You then track its population causing it grow by some chunk size or factor each time it fills up.
Frequent reallocation can be a massive performance drain and by the sounds of the program in question such behaviour seems likely.

Related

How use local array in function - ANSI C?

I want to add something to the end of the array passed to the function.
Which is better, declaring a new larger array or using alloc ()?
1.
void array_append(int *block, size_t size)
{
int new_block[size + 2];
memcpy(new_block, block, size);
(...append)
}
void array_append(int *block, size_t size)
{
int *new_block = calloc(1, sizeof(int) + 2);
memcpy(new_block, block, size);
(...append)
free(new_block);
}
I am not returning the newly created array anywhere.
I only use new_block inside functions.
Does not modify the original array in the function.
Declaring new_block as static is omitted.
I know how calloc() / malloc() works, I know that this operation has to be validated.
new_block is only meant to live in a function.
I just wonder which solution is better and why ...
regards
You should dynamically allocate an array instead of using a variable length array because in general in the last case the code can be unsafe due to a comparatively big size of the array that can lead to the stack overflow.
I want to add something to the end of the array
But you cannot really. Unless with realloc(). This is how your ...append trick can be done, whatever it means.
If you need a temporary array to work with and then copy into your array (but not at the end!), then all methods for allocation are allowed - it really depends on how often and with which sizes.
If it is called very often with limited sizes, it could be a static array.
There is no easy solution for growing arrays (or for memory management in general). At the extreme you allocate every element individually and link them together: a linked list.
--> avoid reaching the end of your arrays. Define a higher maximum or then implement a linked list.
In certain situations realloc() also makes sense (big changes in size, but not often). Problem is sometimes the whole array has to be memcopied to keep the larger array contiguous: "realloc", not "append". So it is "expensive".
I am not returning the newly created array anywhere.
That is part of the problem. You actually seem to be doing half of what realloc() does: allocate the new space, memcpy() the old contents...and then free the old and return the new array(-pointer) to the caller.
First version can not return the array pointer, because end of function is also end of local auto arrays, VLA or not.
If the append can be done to the existing array (which it can if the caller expects this and the memory of the array has room), you can merely append to the existing array.
Otherwise, you need a new array. In this case, the array must be returned to the caller. You can do this by returning a pointer to its first element or by having the caller pass a pointer to a pointer, and you modify the pointed-to pointer to point to the first element of the new array.
When you provide a new array, you must allocate memory for it with malloc or a similar routine. You should not use an array defined inside your function without static, as the memory for such an array is reserved only until execution of the function ends. When your function returns to the caller, that memory is released for other uses. (Generally, you also should not use an array declared with static, but for reasons involving good design, reducing bugs, and multiple serial or parallel calls to the function.)

C, Trouble getting size of array of structs

I'm trying to get the number of elements in an array of structs so I can pass it into another function. Struct:
struct info{
char string1[30];
float float1;
int int1;
char string2[30];
};
Section I'm trying to run:
void function1(){
struct info* temp = build();
printf("flag: %lu %lu %lu\n", sizeof(temp), sizeof(temp[0]), sizeof(temp)/sizeof(temp[0]));
sortFloat(temp, sizeof(temp)/sizeof(temp[0]), 1);
free(temp);
}
build() returns an array of structs after reading in data from a file where each line will be a struct in the array. I'm having trouble passing the size of the array into sortFloat(). The print line returns
flag: 8 72 0
when there are only two lines in the data file. Hard coding that argument as 2 makes the whole program work correctly. Why is this method of counting the elements of the array of structs not?
sizeof(temp)
will not evaluate to the number of elements in the array. It will evaluate to just the size of the pointer.
If you need the size of the array, you can do this:
Change the signature of build to:
struct info* build(int* sizePtr);
Make sure that sizePtr is appropriately set in the implementation.
Then, call it using:
int size;
struct info* temp = build(&size);
What you are thinking of as an array is more precisely just a pointer to the first element. How many elements follow the first element cannot be known to function1(). Only the function build() knows how many elements were read and how much memory was dynamically allocated to store those elements.
The only solution is to get the build() function to also pass back the number of elements read from the file. One way to do this is to send the address of an int variable to build(int *countp) and have build(int *countp) store the count into this int using either ++*countp; as it reads each element or *countp = n; where n is a different variable in which build(...) maintains the count.
Because temp is not an array. It is a pointer. So calling sizeof on it will return the size of the pointer.
It might be hard to understand, but in C, arrays (real arrays, not pointers) are best regarded as value types that are quite tricky to pass around by value. Arrays are not pointers and pointers are not arrays.
sizeof is an operator for determining the size of memory occupied by a value. That is why, when applied to an array, it returns the size of the array, and when applied to a pointer - just the size of the pointer.
What you're creating and returning from build() is most likely a dynamically-allocated (via malloc or friends) buffer of memory. In this case, it was never a real array to begin with! It is just a pointer to a chunk of memory on the heap. This chunk of memory is not one value, and its size cannot be determined using sizeof like that. So you've got no choice but to count the number of allocated structs and get that information to the caller.

Why would you ever want to have an array on the heap?

Why would you ever want to have an array on the heap? My professor gave us two reasons:
To pass the array to functions, instead of passing a copy
So that the array outlives the scope
Can't these both instead by solved by:
Passing a pointer to an array on the stack
Returning the value of the array instead of the array itself (i.e. use the copy constructor)
Could someone give me an example of where an array in the heap has to be used?
Arrays in heap are used to outlive the function's scope. Passing a pointer to an array on the stack is only valid if you don't want to use it later in a previous (upper) caller. And you can't return an array from a function, you can return a pointer to an array, but if it was allocated in stack, it will point to an invalid memory position after the function returns.
The 1st reason is wrong: arrays are never passed by copy. When you call a function, array names always decay into a pointer to its first element, precisely to avoid copying the whole array. If you want to pass an array by copy, you have to embed it inside a struct and pass a struct instead.
Dynamic array allocation is also useful if you don't know the size of your array in advance (although this is not true after C99 brought variable length arrays - but still, variable length arrays are alloced on stack, so you'd have the same problem).
Another good reason to use heap allocation is that you can easily fall out of stack memory for very big arrays. The heap is generally larger.
#include <assert.h>
#include <stdlib.h>
int * f(int* array) {
assert(array[0] == 1); // OK
int static_array[] = {1, 2, 3};
//return static_array = {1, 2, 3}; //BAD: only lives in this function
int * dynamic_array = malloc(sizeof(int) * 2);
dynamic_array[0] = 1;
dynamic_array[1] = 2;
return dynamic_array; // OK: lives outside also
}
int main()
{
int static_array[] = {1, 2, 3};
int * returned_array;
returned_array = f(static_array);
assert(returned_array[0] == 1);
free(returned_array);
}
An array in C is represented as a pointer that references the location of the array data (it points to the first item in the array). In the case of stack-based arrays, the array pointer and data are in the same location. In the case of heap-allocated arrays, the array pointer is on the stack and points to the location on the heap where the array data begins.
For point (2), you cannot return the value of the array. What is returned instead is the location of the array in memory or on the stack. Thus, allocating it on the heap ensures that the data is preserved when returning the array from a function.
A std::vector on the other hand works functionally like an array. With this, the array data is allocated on the heap, but the object that manages the array is on the stack. Thus, the lifetime of the array is controlled by the lifetime of the vector object.
The std::vector has the behaviour you describe:
passing a vector by value to a function causes the data to be copied when passing it to the function;
the vector data only lives for the lifetime of the function.
Passing the vector from a function can cause the array data to be copied. However, this can be optimised using things like return value optimisation and R-value references, which avoid the copy.
If this code runs without crashing you may allocate all your arrays on the stack.
#include <string.h>
int main() {
volatile char buf[1024 * 1024 * 64];
memset(buf, 0, sizeof(buf));
}
Unless you are required to let the array outlive the scope of the function that declares and initialise it, the compiler can do some optimisations that will most likely end up being more efficient then what a programmer can guess. Unless you have time to benchmark and experiment AND that your application is performance critical, leave the optimisation to the compiler.
Reasons you would want to allocate an array on the heap instead of the stack:
The array is very large;
The array's lifetime is outside the scope of any one function;
The array size is not known at compile time, and VLAs are either not available or cannot be used in a particular situation (VLAs cannot be declared static or at file scope, for example);
The array is meant to be resizable.

how to calculate size of pointer pointed memory?

In one function I have written:
char *ab;
ab=malloc(10);
Then in another function I want to know the size of memory pointed by the ab pointer.
Is there any way that I can know that ab is pointing to 10 chars of memory?
No, you don't have a standard way to do this. You have to pass the size of the pointed-to memory along with the pointer, it's a common solution.
I.e. instead of
void f(char* x)
{
//...
}
use
void f(char *x, size_t length)
{
//....
}
and in your code
char *ab = malloc( 10 );
f( ab, 10 );
It's a deep secret that only free() knows for sure. It's likely in your system, but in a totally implementation dependent manner.
A bit awkward, but if you want to keep everything together:
typedef struct
{ // size of data followed by data (C only trick! NOT for C++)
int dimension; // number of data elements
int data[1]; // variable number of data elements
} malloc_int_t;
malloc_int_t *ab;
int dimension = 10;
ab = malloc( sizeof(*ab) + (dimension-1)*sizeof(int) );
ab->dimension = dimension;
ab->data[n] // data access
I've changed the data type to int to make the code a more generic template.
You can't (portably anyway). You have to keep track of the size yourself.
Some implementations of malloc could give you an API to access that information, but there is no provisions in the standard for this.
The size is what you passed into malloc, you can use a global variable or macro to remember it.
There is no way, you have to store the size of the allocated memory in another variable.
No, unfortunately.
You need to pass the size of the block along with the pointer.
No.
Now, that being said, there are non-portable hacks to do this, but it is not safe to rely upon them.
If you know with 100% certainty that the memory was allocated via malloc(), you may be able to rewind the pointer a few bytes and inspect the 'malloc node' that is used to track which parts of memory have been allocated and which have not. However, I can not stress this enough--do not ever depend upon this.
There is no way to deduce the size of allocated memory from the pointer itself. Since ab is a char *, sizeof(ab) is the same as sizeof(char *), which obviously is not the same as the size of the allocated chunk of memory.
Since you called malloc with the required size, you know what the size is. Pass this number along with the pointer to the function that needs to know the size.
I had a structure and a char pointer pointing to its memory address. So relating it to your question, I wanted to find the size of the memory location it was pointing to i.e. the size of the structure. So logically what you do is, find the size of the object the pointer creates to. This worked for me:
unsigned char * buffer= Library1Structure;
int x=sizeof(Library1Structure);
So the value of x tells me the size of the memory location the pointer buffer points to.

How to get the length of dynamically allocated two dimensional arrays in C

The question is how to get the length of dynamically allocated 2D Arrays in C? I thought the code below should get the number of rows, but it doesn't.
char** lines;
/* memory allocation and data manipulation */
int length; //the number of rows
length = sizeof(lines)/sizeof(char*);
Any thoughts on this?
You can't get the length of dynamically allocated arrays in C (2D or otherwise). If you need that information save it to a variable (or at least a way to calculate it) when the memory is initially allocated and pass the pointer to the memory and the size of the memory around together.
In your test case above sizeof is returning the size of the type of lines, and thus your length calculation is equivalent to sizeof(char**)/sizeof(char*) and is likely to have the trivial result of 1, always.
The underlying implementation of malloc or new must inevitably keep track of the size of the memory allocated for your variable. Unfortunately, there is no standard way to get the size of allocated block. The reason is due to the fact that not all memory block are dynamically allocated, so having the function that only works for only dynamic allocation is not so useful.
void fillwithzero(int* array) {
unsigned int size = getsize(array); // return 0 for statically allocated array ??
for(int i = 0; i < size; i++) {
array[i] = 0;
}
}
Let us say we have getsize function that is capable of magically get the size of the dynamically allocated array. However, if you send pointer of a static array, or some array allocated by other means (e.g. external function) to fillwithzero, this function will not be working. That is why most C function that accept array required caller to send the size or the maximum size of the array along with the array itself.
You cannot find the size of an array dynamically allocated.
If you need pass this array to a function, create a structure containing the array and its size.
struct Line {
char** text;
uint32_t size;
};
You cannot get the length of a dynamically allocated array in C.
When you allocate it, you need to store that length somewhere, so you know how long it is.
For instance:
int length = ...;
lines = malloc(length*sizeof(char*));
If you need to pass this around to other functions, you will need to either pass them as separate parameters, or define a struct type that includes the length and the lines pointer.
You pass it along with your value. There's no way to find that out.
You can get the length of dynamically allocated memory, IF you use the NONPORTABLE MSVC/MinGW extension:
#include <malloc.h>
char *m = malloc(1234);
#ifdef __int64
printf("m size = %lu bytes", _msize(m) );
#endif

Resources