2D Ring buffers in C - c

I have coded a simple ring buffer which has a ring size of 5 to store values of type A.
Now I have to extend this buffer to store type B values(also 5 values).
To give an overview, I have defined the variables for read index and write index as global volatile and two functions for reading and writing on the ring buffer.
I only have to do : ring data = int read_ring_data() and write_ring_data(int pass_new_data)
The volatile global variables help control the locations of read and write.
My question is, is there a way to reuse these read and write functions for extending it to a 2D buffer by simply re-dimensioning it? How do I implement it?

You can still code in an object oriented style in C , simply using struct's as classes, and 'methods' are just functions that take a pointer to a class. I would create a general purpose 'ring-buffer' 'class' in C as follows..
typedef struct RingBuffer {
int elemSize;
int headIndex; // index to write
int tailIndex; // index to read
int maxIndex;
void* buffer;
}
RingBuffer;
// initialize a new ring-buffer object
void RingBuffer_Init(RingBuffer* rb, int elemSize, int maxNum) {
rb->elemSize=elemSize; rb->headIndex = 0; rb->tailIndex=0; rb->buffer = malloc(elemSize*maxNum);
rb->maxIndex=maxNum;
}
void RingBuffer_Read(RingBuffer* rb, void* dstItem){ // copy into buffer, update index
void* src=rb->buffer + rb->tailIndex*rb->elemSize;
memcpy(dstItem,src,rb->elemSize);
rb->tailIndex++; ....//wrapround, assert etc..
}
void RingBuffer_Write(RingBuffer* rb, const void * srcItem) { // copy from buffer,update indices
}// etc..
you'd have to take care of allocating the RingBuffer structs of course, some people might do that with some macro if they adopt a consistent naming scheme for 'init'(equiv of c++ constructor) and 'shutdown'/'release' functions
Of course there are many permutations.. it would be very easy to make a ring buffer into which you can read/write variable sized elements, perhaps writing the element size into the buffer at each point. it would certainly be possible to resize on the fly aswell, even change the element size.
Although the language support for creating data structures is more primitive in C than in C++, sometimes re-working a problem to use simple data structures can have performance benefits. Also treating data structures as simple blocks of memory with size passed as a parameter may cause less compiler inlining: compact code can have advantages as the default method to use outside of inner loops (i-cache coherency).
it would be possible to combine the 'Buffer Header' structure and the array data into one allocation, (just assume the buffer data follows the header structure in memory), which reduces the amount of pointer-dereferencing going on.

Related

Is it ok to create a large array in the heap when you aren't necessarily using all of it?

So I'm looking at a solution to some coding interview type questions, and there's an array inside a struct
#define MAX_SIZE 1000000
typedef struct _heap {
int data[MAX_SIZE];
int heap_size;
}heap;
heap* init(heap* h) {
h = (heap*)malloc(sizeof(heap));
h->heap_size = 0;
return h;
}
This heap struct is later created like so
heap* max_heap = NULL;
max_heap = init(max_heap);
First of all, I'd wish this was written in C++ style than C, but secondly if I'm just conscerned about the array, I'm assuming it is equivalent to solely analyze the array portion by changing the code like this
int* data = NULL;
data = (int*)malloc(1000000 * sizeof(int));
Now in that case, is there any problems with declaring the array with the max size if you are probably just using a little bit of it?
I guess this boils down to the question of when an array is created in the heap, how does the system block out that portion of the memory? In which case does the system prevent you from accessing memory that is part of the array? I wouldn't want a giant array holding up space if I'm not using much of it.
is there any problems with declaring the array with the max size if you are probably just using a little bit of it?
Yes. The larger the allocation size the greater the risk of an out-of-memory error. If not here, elsewhere in code.
Yet some memory allocation systems handle this well as real memory allocations do not immediately occur, but later when needed.
I guess this boils down to the question of when an array is created in the heap, how does the system block out that portion of the memory?
That is an implementation defined issue not defined by C. It might happen immediately or deferred.
For maximum portability, code would take a more conservative approach and allocate large memory chunks only as needed, rather than rely on physical allocation occurring in a delayed fashion.
Alternative
In C, consider a struct with a flexible member array.
typedef struct _heap {
size_t heap_size;
int data[];
} heap;

Is it good programming practice in C to use first array element as array length?

Because in C the array length has to be stated when the array is defined, would it be acceptable practice to use the first element as the length, e.g.
int arr[9]={9,0,1,2,3,4,5,6,7};
Then use a function such as this to process the array:
int printarr(int *ARR) {
for (int i=1; i<ARR[0]; i++) {
printf("%d ", ARR[i]);
}
}
I can see no problem with this but would prefer to check with experienced C programmers first. I would be the only one using the code.
Well, it's bad in the sense that you have an array where the elements does not mean the same thing. Storing metadata with the data is not a good thing. Just to extrapolate your idea a little bit. We could use the first element to denote the element size and then the second for the length. Try writing a function utilizing both ;)
It's also worth noting that with this method, you will have problems if the array is bigger than the maximum value an element can hold, which for char arrays is a very significant limitation. Sure, you can solve it by using the two first elements. And you can also use casts if you have floating point arrays. But I can guarantee you that you will run into hard traced bugs due to this. Among other things, endianness could cause a lot of issues.
And it would certainly confuse virtually every seasoned C programmer. This is not really a logical argument against the idea as such, but rather a pragmatic one. Even if this was a good idea (which it is not) you would have to have a long conversation with EVERY programmer who will have anything to do with your code.
A reasonable way of achieving the same thing is using a struct.
struct container {
int *arr;
size_t size;
};
int arr[10];
struct container c = { .arr = arr, .size = sizeof arr/sizeof *arr };
But in any situation where I would use something like above, I would probably NOT use arrays. I would use dynamic allocation instead:
const size_t size = 10;
int *arr = malloc(sizeof *arr * size);
if(!arr) { /* Error handling */ }
struct container c = { .arr = arr, .size = size };
However, do be aware that if you init it this way with a pointer instead of an array, you're in for "interesting" results.
You can also use flexible arrays, as Andreas wrote in his answer
In C you can use flexible array members. That is you can write
struct intarray {
size_t count;
int data[]; // flexible array member needs to be last
};
You allocate with
size_t count = 100;
struct intarray *arr = malloc( sizeof(struct intarray) + sizeof(int)*count );
arr->count = count;
That can be done for all types of data.
It makes the use of C-arrays a bit safer (not as safe as the C++ containers, but safer than plain C arrays).
Unforntunately, C++ does not support this idiom in the standard.
Many C++ compilers provide it as extension though, but it is not guarantueed.
On the other hand this C FLA idiom may be more explicit and perhaps more efficient than C++ containers as it does not use an extra indirection and/or need two allocations (think of new vector<int>).
If you stick to C, I think this is a very explicit and readable way of handling variable length arrays with an integrated size.
The only drawback is that the C++ guys do not like it and prefer C++ containers.
It is not bad (I mean it will not invoke undefined behavior or cause other portability issues) when the elements of array are integers, but instead of writing magic number 9 directly you should have it calculate the length of array to avoid typo.
#include <stdio.h>
int main(void) {
int arr[9]={sizeof(arr)/sizeof(*arr),0,1,2,3,4,5,6,7};
for (int i=1; i<arr[0]; i++) {
printf("%d ", arr[i]);
}
return 0;
}
Only a few datatypes are suitable for that kind of hack. Therefore, I would advise against it, as this will lead to inconsistent implementation styles across different types of arrays.
A similar approach is used very often with character buffers where in the beginning of the buffer there is stored its actual length.
Dynamic memory allocation in C also uses this approach that is the allocated memory is prefixed with an integer that keeps the size of the allocated memory.
However in general with arrays this approach is not suitable. For example a character array can be much larger than the maximum positive value (127) that can be stored in an object of the type char. Moreover it is difficult to pass a sub-array of such an array to a function. Most of functions that designed to deal with arrays will not work in such a case.
A general approach to declare a function that deals with an array is to declare two parameters. The first one has a pointer type that specifies the initial element of an array or sub-array and the second one specifies the number of elements in the array or sub-array.
Also C allows to declare functions that accepts variable length arrays when their sizes can be specified at run-time.
It is suitable in rather limited circumstances. There are better solutions to the problem it solves.
One problem with it is that if it is not universally applied, then you would have a mix of arrays that used the convention and those that didn't - you have no way of telling if an array uses the convention or not. For arrays used to carry strings for example you have to continually pass &arr[1] in calls to the standard string library, or define a new string library that uses "Pascal strings" rather then "ASCIZ string" conventions (such a library would be more efficient as it happens),
In the case of a true array rather then simply a pointer to memory, sizeof(arr) / sizeof(*arr) will yield the number of elements without having to store it in the array in any case.
It only really works for integer type arrays and for char arrays would limit the length to rather short. It is not practical for arrays of other object types or data structures.
A better solution would be to use a structure:
typedef struct
{
size_t length ;
int* data ;
} intarray_t ;
Then:
int data[9] ;
intarray_t array{ sizeof(data) / sizeof(*data), data } ;
Now you have an array object that can be passed to functions and retain the size information and the data member can be accesses directly for use in third-party or standard library interfaces that do not accept the intarray_t. Moreover the type of the data member can be anything.
Obviously NO is the answer.
All programming languages has predefined functions stored along with the variable type. Why not use them??
In your case is more suitable to access count /length method instead of testing the first value.
An if clause sometimes take more time than a predefined function.
On the first look seems ok to store the counter but imagine you will have to update the array. You will have to do 2 operations, one to insert other to update the counter. So 2 operations means 2 variables to be changed.
For statically arrays might be ok to have them counter then the list, but for dinamic ones NO NO NO.
On the other hand please read programming basic concepts and you will find your idea as a bad one, not complying with programming principles.

Avoiding freeing a string literal

If you have a function in C that takes ownership of whatever is passed into it, such as a function that adds a struct to a vector buffer by-value, and this struct value contains a member pointer to a character array (a string).
During the buffer's cleanup routine, it should release the strings that it owns, but what if some strings are allocated at runtime, but others are allocated at compiletime using a string literal.
There is no safe and standard (non-proprietary) way to detect if a char* points to read-only memory, so what is this hypothetical freeVector function to do with a pointer to a char buffer?
struct Element {
int id;
char* name;
}
struct Vector {
size_t maxIndex;
size_t length;
struct Element buffer[];
}
void addToVector(struct Vector* vector, struct Element element) {
// lazy-reallocation logic here if maxIndex => length
vector->buffer[ vector->maxIndex++ ] = element; // by-value copy
}
void freeVector(struct Vector* vector) {
for(size_t i = 0; i < vector->maxIndex; i++ ) {
free( vector->buffer[ i ].name ); // segfault/AV if name is a literal
}
}
The blessing and the curse of C is that it lets this totally up to you. Two choices are to allocate everything on the heap and to define a fat pointer type that includes a bit to say whether each instance needs freeing. A clever albeit non-portable implementation might use a low order bit of the pointer itself because for many architectures the bottom 2 bits or more of all pointers are always zero. Garbage collectors have used this trick to distinguish pointers from unboxed discrete types (fixnums in the biz) almost forever.
If you allow more than one pointer to the same object (think graph data structure), then things get more complex or interesting depending on your point of view. For this, you'll probably need a garbage collection scheme: obstacks, reference counting, mark and sweep, arena copying, etc. Other languages tend to give you one of these as a built-in or (as in C++) language features deliberately meant to support implementing one or more yourself. With C, not so much...

How to include a variable-sized array as stuct member in C?

I must say, I have quite a conundrum in a seemingly elementary problem. I have a structure, in which I would like to store an array as a field. I'd like to reuse this structure in different contexts, and sometimes I need a bigger array, sometimes a smaller one. C prohibits the use of variable-sized buffer. So the natural approach would be declaring a pointer to this array as struct member:
struct my {
struct other* array;
}
The problem with this approach however, is that I have to obey the rules of MISRA-C, which prohibits dynamic memory allocation. So then if I'd like to allocate memory and initialize the array, I'm forced to do:
var.array = malloc(n * sizeof(...));
which is forbidden by MISRA standards. How else can I do this?
Since you are following MISRA-C, I would guess that the software is somehow mission-critical, in which case all memory allocation must be deterministic. Heap allocation is banned by every safety standard out there, not just by MISRA-C but by the more general safety standards as well (IEC 61508, ISO 26262, DO-178 and so on).
In such systems, you must always design for the worst-case scenario, which will consume the most memory. You need to allocate exactly that much space, no more, no less. Everything else does not make sense in such a system.
Given those pre-requisites, you must allocate a static buffer of size LARGE_ENOUGH_FOR_WORST_CASE. Once you have realized this, you simply need to find a way to keep track of what kind of data you have stored in this buffer, by using an enum and maybe a "size used" counter.
Please note that not just malloc/calloc, but also VLAs and flexible array members are banned by MISRA-C:2012. And if you are using C90/MISRA-C:2004, there are no VLAs, nor are there any well-defined use of flexible array members - they invoked undefined behavior until C99.
Edit: This solution does not conform to MISRA-C rules.
You can kind of include VLAs in a struct definition, but only when it's inside a function. A way to get around this is to use a "flexible array member" at the end of your main struct, like so:
#include <stdio.h>
struct my {
int len;
int array[];
};
You can create functions that operate on this struct.
void print_my(struct my *my) {
int i;
for (i = 0; i < my->len; i++) {
printf("%d\n", my->array[i]);
}
}
Then, to create variable length versions of this struct, you can create a new type of struct in your function body, containing your my struct, but also defining a length for that buffer. This can be done with a varying size parameter. Then, for all the functions you call, you can just pass around a pointer to the contained struct my value, and they will work correctly.
void create_and_use_my(int nelements) {
int i;
// Declare the containing struct with variable number of elements.
struct {
struct my my;
int array[nelements];
} my_wrapper;
// Initialize the values in the struct.
my_wrapper.my.len = nelements;
for (i = 0; i < nelements; i++) {
my_wrapper.my.array[i] = i;
}
// Print the struct using the generic function above.
print_my(&my_wrapper.my);
}
You can call this function with any value of nelements and it will work fine. This requires C99, because it does use VLAs. Also, there are some GCC extensions that make this a bit easier.
Important: If you pass the struct my to another function, and not a pointer to it, I can pretty much guarantee you it will cause all sorts of errors, since it won't copy the variable length array with it.
Here's a thought that may be totally inappropriate for your situation, but given your constraints I'm not sure how else to deal with it.
Create a large static array and use this as your "heap":
static struct other heap[SOME_BIG_NUMBER];
You'll then "allocate" memory from this "heap" like so:
var.array = &heap[start_point];
You'll have to do some bookkeeping to keep track of what parts of your "heap" have been allocated. This assumes that you don't have any major constraints on the size of your executable.

Dynamically create an array of TYPE in C

I've seen many posts for c++/java, but nothing for C. Is it possible to allocate memory for an array of type X dynamically during run time? For example, in pseudo,
switch(data_type)
case1:float, create a new array of floats to use in the rest of the program
case2:int, create new array of ints to use in the rest of the program
case3:unsigned, ....
// etc.
In my program I determine the data type from a text header file during run time, and then I need to create an appropriate array to store/manipulate data. Is there some kind of generic type in C?
EDIT: I need to dynamically create and DECIDE which array should be created.
Thanks,
csand
Assuming you calculate the total size, in bytes, required from the array, you can just allocate that much memory and assign it to the correct pointer type.
Ex:
void * data_ptr = malloc( data_sz );
then you can assign it to a pointer for whatever type you want:
int *array1 = (int *)data_ptr;
or
float *array2 = (float *)data_ptr;
NOTE: malloc allocates memory on the heap, so it will not be automatically freed. Make sure you free the memory you allocate at some point.
UPDATE
enum {
DATA_TYPE_INT,
DATA_TYPE_FLOAT,
...
};
typedef struct {
int data_type;
union {
float * float_ptr;
int * int_ptr;
...
} data_ptr;
} data;
While this might allow you to store the pointer and tell what type of pointer you should be using, it still leaves the problem of not having to branch the behavior depending on the data type. That will be difficult because the compiler has to know the data type for assignments etc.
You're going to have a hard time doing this in C because C is statically typed and has no run-time type information. Every line of C code has to know exactly what type it is dealing with.
However, C comes with a nifty and much-abused macro preprocessor that lets you (among other things) define new functions that differ only in the static type. For example:
#define FOO_FUNCTION(t) t foo_function_##t(t a, t b) { return a + b; }
FOO_FUNCTION(int)
FOO_FUNCTION(float)
This gets you 2 functions, foo_function_int and foo_function_float, which are identical other than the name and type signature. If you're not familiar with the C preprocessor, be warned it has all sorts of fun gotchas, so read up on it before embarking on rewriting chunks of your program as macros.
Without knowing what your program looks like, I don't know how feasible this approach will be for you, but often the macro preprocessor can help you pretend that you're using a language that supports generic programming.

Resources