Creating dynamic vector on predefined struct - c

I have a predefined struct to use :
typedef struct somestruct_s {
int s;
union {
unsigned char *ptr;
unsigned char l_ptr[sizeof(char *)];
};
}somestruct_t, *somestruct;
It contains union to reduce memory usage.
I know the size can vary due to m32 and m64 compilation (pointer size).
My question is how to "use" that struct for my precise assignment. The purpose of this struct is to implement basic bit operations, the s variable contains the size of the bitmap in bytes. If the bitmap can fit inside of memory occupied by pointer to bitmap then we allocate her there. Im writing some bitmap operations on it, but i can't really get the struct or how to operate on it.

I cannot understand what your problem is. You have to have one major function which will return correct pointer to bitmap depending on pointer size:
unsigned char* somestruct_get_bitmap(somestruct_t* ths) {
if( sizeof(char*) > ths->s )
return ths->ptr;
return ths->l_ptr;
}
all other functions must use this function to get the correct pointer to bitmap. Also you need the constructor/destructor pair to initialize/deinitialize bitmap pointer in the correct way (of cause I am showing the simplest example supposing that you have null-terminated bitmaps):
unsigned char* somestruct_init(somestruct_t* ths, unsigned char* ptr) {
ths->s = strlen(ptr) + 1;
if( sizeof(char*) > ths->s ) {
ths->ptr = strdup(ptr);
return;
}
strcpy(ths->l_ptr, ptr);
}
unsigned char* somestruct_destroy(somestruct_t* ths) {
if( sizeof(char*) > ths->s ) {
free(ths->ptr);
return;
}
}

Related

Buffer Array Usage in C

My mind tells me there is something wrong here, like maybe I won't be able to append a value to the last element in the array, or it will exceed the UINT8 when doing the cbuf_length++ and crash? My mind thinks something is wrong, but i just can't see what it is. What is the best way to use arrays that will allow me to append to all 256 elements in the array without crashing or confusing the next programmer?
#define CBUF_SIZE 256
static UINT8 cbuf[CBUF_SIZE];
static UINT8 cbuf_length;
void CBUF_AppendChar(char c)
{
if (cbuf_length < CBUF_SIZE) {
cbuf[cbuf_length] = c;
cbuf_length++;
}
}
First, there's some issues with your code.
UINT8 is not a standard type, I suspect it's a Microsoft type. Unless you have a good reason, use uint8_t from stdint.h.
Second, cbuf_length < CBUF_SIZE is always true because uint8_t can't store higher than 255.
test.c:10:21: warning: comparison of constant 256 with expression of type 'uint8_t'
(aka 'unsigned char') is always true [-Wtautological-constant-out-of-range-compare]
if (cbuf_length < CBUF_SIZE) {
~~~~~~~~~~~ ^ ~~~~~~~~~
More important, global variables and constants should be avoided. They create complexity, limit you to a single instance, cause problems with concurrency. It's not always clear which global variables must be updated together. It's also not immediately clear what functions affect what data.
Instead, consider using a struct.
For array sizes use size_t to avoid exactly the sort of bug you have where the size of the array is larger than the capacity of your type. size_t is the type for storing, you guessed it, sizes! It will always be large enough.
Finally, don't forget error handling. Like when your buffer can hold no more elements. In this case I have the append function return a boolean which can be checked to see if the append succeeded. (I've been sloppy in a few other places, like not checking malloc).
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
typedef struct {
uint8_t *buf;
size_t size;
size_t capacity;
} cbuf;
cbuf *cbuf_new( size_t capacity ) {
cbuf *self = malloc( sizeof(cbuf) );
self->size = 0;
self->capacity = capacity;
self->buf = malloc( capacity * sizeof(uint8_t) );
return self;
}
bool cbuf_append( cbuf *self, char c) {
// Get the error check out of the way early.
if( self->size >= self->capacity ) {
return false;
}
// Don't forget to cast signed char to uint8_t.
self->buf[self->size] = (uint8_t)c;
self->size++;
return true;
}
int main(void) {
cbuf *buf = cbuf_new(2);
cbuf_append(buf, 'f'); // true
cbuf_append(buf, 'o'); // true
cbuf_append(buf, 'o'); // false
// Prints 'fo'
for( size_t i = 0; i < buf->size; i++ ) {
printf("%c", buf->buf[i]);
}
puts("");
}
All the information about the buffer is collected together in a single struct. Now it's immediately clear that cbuf_append works on buf. You can have multiple buffers if you wish.
If you really want a statically allocated buffer, a slight modification gives you optional control of the memory allocation.
cbuf *cbuf_new_from_buf( uint8_t *buf, size_t capacity ) {
cbuf *self = malloc( sizeof(cbuf) );
self->size = 0;
self->capacity = capacity;
self->buf = buf;
bzero( self->buf, self->capacity );
return self;
}
cbuf *cbuf_new( size_t capacity ) {
return cbuf_new_from_buf(
malloc( capacity * sizeof(uint8_t) ),
capacity
);
}
Now you can still use cbuf_new() to let it take care of memory allocation for you. Or you can use cbuf_new_from_buf() to use an existing buffer you've already allocated.
uint8_t mybuf[2];
cbuf *buf = cbuf_new_from_buf(mybuf, sizeof(mybuf));
But you shouldn't be writing your own buffers!
This is all fine for a learning exercise. But in production if all you want is a sized array you can append to, don't write a bunch of code that you'll (or somebody else) will have to document and maintain and test and fix and add features to. Use an existing library. Like GLib's GArray type. It does what you want and more.
#include <glib.h>
#include <stdio.h>
#include <stdint.h>
int main(void) {
// Start with a size 2 buffer, it will grow as needed.
GArray *buf = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), 2);
uint8_t c = 'f';
g_array_append_val(buf, c);
c = 'o';
g_array_append_val(buf, c);
c = 'o';
g_array_append_val(buf, c); // It will grow the buffer.
for( guint i = 0; i < buf->len; i++ ) {
printf("%c", g_array_index(buf, uint8_t, i));
}
puts("");
}
While GArray has some quirks, like not being able to append literals, it's well documented, powerful, and fast. That means you can spend your time on the real code, not basic data structures.
Even better, because the array will grow if necessary there's no chance of a buffer overflow and no need to check if the append succeeded. Your original concern about the buffer size is eliminated, the buffer will just grow as necessary.
The only mistake is in the type of cbuf_length — after 255, it will overflow to 0. Defining it as a larger type (UINT16 or even just unsigned) will fix it.
Other than that, it's perfectly valid and understandable code. You might want to return something from that function, though — some boolean result telling the caller whether the value was appended successfully or not.

Storing control information alongside allocated memory. Is it portable?

Very briefly, we are trying to write some allocation routines (of type unsigned char) where each allocated block has some control information associated with it. We are not trying to write a full fledged memory manager but have some specific requirement
A sample of our control structure
typedef struct _control_data
{
u8 is_segment;
:
:
:
struct _control_data* next;
}control_data;
When the user calls alloc for size 40, we will allocate
unsigned char* data_ptr = (unsigned char*)malloc(sizeof(control_data) + size);
return(&data_ptr[sizeof(control_data]);
Later the user will pass the pointer returned during alloc and we want to access the control information.
void do_some_processing(unsigned char* data_ptr)
{
struct control_data* c_ptr = (data_ptr - sizeof(control_data));
c_ptr->is_segment = TRUE;
c_ptr->next = NULL;
}
Is the above access legal and portable?
Yes, it should be fine and is a common technique.
A few points:
Don't cast the return value of malloc() in C.
Use pointer arithmetic to your advantage:
void * my_alloc(size_t size)
{
control_data *cd = malloc(size + sizeof *cd);
if(cd != NULL)
return cd + 1;
return NULL;
}
The + 1 will do exactly the right thing, but is way simpler. Also there's no point in making the allocation "typed"; let it return void * and leave it up to the caller to use an unsigned char * pointer to store the returned value.
UPDATE: As pointed out in a comment, this ignores alignment (which feels safe since you say the non-control data is an array of unsigned char) which might be a problem in the general case.

Declare array in struct

I am trying to make a struct for a circular buffer that contains an array of type "quote." However, the quote array must start out at a size of 10. I am trying to figure out if I declare the size of 10 in my .h file or in my .c file. My two files are as follows:
.h file:
typedef struct{
unsigned int time;
double rate;
}quote;
typedef struct{
unsigned int testNum;
quote quoteBuffer[];
}cbuf;
cbuf* cbuf_init();
.c file:
cbuf* cbuf_init(){
cbuf *buffer = (cbuf *)calloc(1,sizeof(cbuf));
buffer->testNum = 1;
quote newQuote = {1,1.00};
buffer->quoteBuffer[1] = newQuote;
return buffer;
}
These are obviously just test values, however if I wanted to specifically make the quote array in the cbuf struct start out at a size of 10, would I declare that in the .h file as:
typedef struct{
unsigned int testNum;
quote quoteBuffer[10];
}cbuf;
or in the .c file some other way?
There are two ways of having dynamic arrays in structures. The obvious is of course to have it as a pointer, and dynamically allocate (or reallocate) when needed.
The other is to have an array of size 1, and then allocate a larger size than the structure, to accommodate for the array:
typedef struct {
unsigned int testNum;
quote quoteBuffer[1];
} cbuf;
cbuf *cbuf_init(const size_t num_quotes) {
/* Allocate for the `cbuf` structure, plus a number of `quote`
* structures in the array
*/
cbuf *buffer = malloc(sizeof(cbuf) + (num_quotes - 1) * sizeof(quote));
/* Other initialization */
return buffer;
}
/* If more quotes are needed after initial allocation, use this function */
cbuf *cbuf_realloc(cbuf *buffer, const size_t new_num_quotes) {
buffer = realloc(buffer, sizeof(cbuf) + (new_num_quotes - 1) * sizeof(quote));
/* Other initialization */
return buffer;
}
Now you can use the array as a normal array:
cbuf *buffer = cbuf_init();
buffer->quoteBuffer[5].time = 123;
Note: I only allocate extra space for 9 quote structures, but state that I allocate ten. The reason is that the cbuf structure already contains one quote structure in its array. 1 + 9 = 10. :)
Note 2: I put the quote array in the cbuf structure with one entry already in it for backwards compatibility. Having an array without a size in the structure is quite new in the C world.
you can also do this if you want 10 quotes in a cbuf but a statically allocated like quote buffer[10] would work too:
cbuf* cbuf_init(int numQuotes)
{
cbuf *b = calloc(1, sizeof(cbuf) + numQuotes * sizeof(quote));
return b;
}
If you want a statically sized circular buffer then your could declare the size in the header file. Using a #define for the buffer size will make the code more readable and maintainable, as you'll reference the size elsewhere in your code.
If you want the circular buffer to be growable then define the size in your C file. You'll then have to take care of tracking the size and destroying the memory that you will have to allocate dynamically.
In your example, I think you need to allocate more room for your quote structs...
cbuf *buffer = (cbuf *)calloc(1,sizeof(cbuf) + NUM_QUOTES*sizeof(struct quote));
---------------------------------
The reason for this is that in your struct def...
quote quoteBuffer[];
... quoteBuffer doesn't add size to the struct. quoteBuffer will point to one byte past the end of the struct, hence the need to allocate memory for the struct + memory for the array.
EDIT: Daniel Fischer's comment (thanks Daniel) - quoteBuffer may, in some cases, add size to the struct if it introduces padding. The reason is that the compiler will probably strive to get the most optimal alignment for quoteBuffer. For example, ints normally aligned of 4-byte boundaries. E.g. a struct like:
struct {
char a;
int b;
}
is probably changed by compiler to
struct {
char a;
char pad[3]; // compiler adds padding behind the scenes
int b; // align b on a 4-byte boundary
}
This probs doesn't apply in your case as your struct leaves quoteBuffer[] on a 4 byte boundary.
The reason that the compiler does this is two fold.
1. On some architectures (not so common nowadays I think?), unaligned accesses aren't supported.
2. Aligned accesses are more efficient, even if architecture allows non-aligned accesses as it is one memory read as opposed to two memory reads plus a manipulation.

how to create a dynamic array of structs in C

I want to send a struct of symbol from one function to other functions, and i want to create an array that every cell will point to a different values of the following struct:
typedef struct symbol_def
{
char* sym_name;
char* sym_type;
unsigned short sym_address;
char sym_is_ext;
}symbol;
I'm trying to run this code:
//function-1
void compile_input_file(char* input)
{
symbol* curr_symbol;
//Intalize curr_symbol struct
curr_symbol = (symbol*)malloc(sizeof(symbol));
//memset((void)curr_symbol, 0, sizeof(symbol));
parse_command(line, &parser, curr_symbol, &index);
}
//function-2
void parse_command(char* line, parse_params* parser, symbol* curr_symbol, int* index)
{
sym = symbol_table_create(curr_symbol, "directive", sym_label, '0', index);
}
//function-3
symbol* symbol_table_create(symbol* curr_symbol,char* s_type, char* label, char is_ext, int* index)
{
int temp = *index;
curr_symbol = (symbol*)realloc(curr_symbol,sizeof(symbol*)*(temp+1));
curr_symbol[temp].sym_type = s_type;
curr_symbol[temp].sym_name = label;
curr_symbol[temp].sym_address = 0;
curr_symbol[temp].sym_is_ext = is_ext;
temp++;
*index = temp;
return curr_symbol;
}
The problem is that the curr_symbol gets override all the time.
my purpose is to build a table of symbols, that in every iteration on the code i'll add another cell to the array
any ideas?
There is a problem, with the realloc It should be curr_symbol = (symbol*)realloc(curr_symbol,sizeof(symbol)*(temp+1)); You were actually allocating it sizeof pointer which is 4 Bytes.
A Piece of Advice Realloc is a costly operation you should use it only if necessary and not on every instance
you could malloc in function3 instead of function1. If you do so you dont even need to pass the pointer via function2.
or else put a check to see if realloc is really necessary or not. Eg:- Check if the pointer is allocated memory. if(ptr!=null){ //realloc } This can work as a checking case too.
Best of Luck. :)

how can i know the allocated memory size of pointer variable in c [duplicate]

This question already has answers here:
Determine size of dynamically allocated memory in C
(15 answers)
Closed 3 years ago.
I have faced some problem in this case can you please your ideas.
main()
{
char *p=NULL;
p=(char *)malloc(2000 * sizeof(char));
printf("size of p = %d\n",sizeof (p));
}
In this program Its print the 4 that (char *) value,but i need how many bytes allocated for
that.
You could also implement a wrapper for malloc and free to add tags (like allocated size and other meta information) before the pointer returned by malloc. This is in fact the method that a c++ compiler tags objects with references to virtual classes.
Here is one working example:
#include <stdlib.h>
#include <stdio.h>
void * my_malloc(size_t s)
{
size_t * ret = malloc(sizeof(size_t) + s);
*ret = s;
return &ret[1];
}
void my_free(void * ptr)
{
free( (size_t*)ptr - 1);
}
size_t allocated_size(void * ptr)
{
return ((size_t*)ptr)[-1];
}
int main(int argc, const char ** argv) {
int * array = my_malloc(sizeof(int) * 3);
printf("%u\n", allocated_size(array));
my_free(array);
return 0;
}
The advantage of this method over a structure with size and pointer
struct pointer
{
size_t size;
void *p;
};
is that you only need to replace the malloc and free calls. All other pointer operations require no refactoring.
There is no portable way but for windows:
#include <stdio.h>
#include <malloc.h>
#if defined( _MSC_VER ) || defined( __int64 ) /* for VisualC++ or MinGW/gcc */
#define howmanybytes(ptr) ((unsigned long)_msize(ptr))
#else
#error no known way
#endif
int main()
{
char *x=malloc(1234);
printf( "%lu", howmanybytes(x) );
return 0;
}
Although it may be possible that some libraries allows you to determine the size of an allocated buffer, it wouldn't be a standard C function and you should be looking at your library's own documentations for this.
However, if there are many places that you need to know the size of your allocated memory, the cleanest way you could do it is to keep the size next to the pointer. That is:
struct pointer
{
size_t size;
void *p;
};
Then every time you malloc the pointer, you write down the size in the size field also. The problem with this method however is that you have to cast the pointer every time you use it. If you were in C++, I would have suggested using template classes. However, in this case also it's not hard, just create as many structs as the types you have. So for example
struct charPtr
{
size_t size;
char *p;
};
struct intPtr
{
size_t size;
int *p;
};
struct objectPtr
{
size_t size;
struct object *p;
};
Given similar names, once you define the pointer, you don't need extra effort (such as casting) to access the array. An example of usage is:
struct intPtr array;
array.p = malloc(1000 * sizeof *array.p);
array.size = array.p?1000:0;
...
for (i = 0; i < array.size; ++i)
printf("%s%d", i?" ":"", array.p[i]);
printf("\n");
It is impossible to know how much memory was allocated by just the pointer. doing sizeof (p) will get the size of the pointer variable p which it takes at compile time, and which is the size of the pointer. That is, the memory the pointer variable takes to store the pointer variable p. Inside p the starting address of the memory block is stored.
Once you allocate some memory with malloc it will return the starting address of the memory block, but the end of the block cannot be found from it, as there is no terminator for a block. You define the end of the block therefore you need to identify it by any means, so store it somewhere. Therefore you need to preserve the block length somewhere to know where the block which is pointed to by p ends.
Note: Although the memory allocation structure keeps track of allocated and unallocated blocks, therefore we can know the allocated memory block length from these structures, but these structures are not available to be used by the users, unless any library function provides them. Therefore a code using such feature is not portable (pointed by #Rudy Velthuis) . Therefore it is the best to keep track of the structure yourself.
You need to keep track of it in a variable if you want to know it for later:
char *p = NULL;
int sizeofp = 2000*sizeof(char);
p = (char *)malloc(sizeofp);
printf("size of p = %d\n",sizeofp);
You cannot use the sizeof in this case, since p is a pointer, not an array, but since you allocate it, you already know:
main()
{
size_t arr_size = 2000;
char *p=NULL;
p=malloc(arr_size * sizeof(char));
printf("size of p = %d\n",arr_size);
}
Edit - If the malloc fails to allocate the size you wanted, it won't give you a pointer to a smaller buffer, but it will return NULL.

Resources