Initializing pointers in a struct in a minimum of source lines - c

I'm currently new to C programming, and appreciate for any tip.
Is there a shorter way to initialize struct pointers in C without removing the pointer tags?
typedef struct {
int x, y, z;
} Point3;
typedef struct {
Point3 *pos, *direction;
} Vector;
int main() {
Vector *p;
p = malloc(sizeof(Vector));
p->pos = malloc(sizeof(Point3));
p->direction = malloc(sizeof(Point3));
return 0;
}

Yes, there is a shorter way — one which is one malloc() call shorter.
Vector *p = malloc(sizeof(Vector));
if (p != 0)
{
p->pos = malloc(2 * sizeof(Point3));
if (p->pos != 0)
p->direction = &p->pos[1];
}
Allocate an array of 2 Point3 values. p->pos points to the first, and p->direction points to the second (or vice versa).
It is still 3 statements (plus error checking) and two calls to malloc(), though.
In practice, you could almost certainly get away with:
Vector *p = malloc(sizeof(Vector) + 2 * sizeof(Point3));
if (p != 0)
{
p->pos = (void *)((char *)p + sizeof(Vector));
p->direction = (void *)((char *)p + sizeof(Vector) + sizeof(Point3));
}
I am not sure that is sanctioned by the C standard, but I can't immediately think of a plausible platform configuration where it would actually fail to work correctly. It would fail if you found some bizarre platform where addresses were 16-bits each but int was 8 bytes and had to be 8-byte aligned, but that's hardly plausible.

To me, it makes far more sense to put the Point3 members directly in the Vector, instead of pointers. Fewer allocations, less memory fragmentation, fewer de-references, fewer cache-misses.
typedef struct {
int x, y, z;
} Point3;
typedef struct {
Point3 pos, direction;
} Vector;
int main(void) {
/* Local (stack) allocation of a Vector, initialized to all zeros */
Vector v = {};
/* Dynamic (heap) allocation of a Vector, initialized to all zeros */
Vector *p;
p = malloc(sizeof(Vector));
if (!p) {
return 1; // failure
}
*p = (Vector){};
return 0;
}

Unfortunately, there is no other way. You can simplify memory allocation with another function, like this
Vector* allocate_vector( ) {
Vector* v = (Vector*)malloc( sizeof(Vector) );
if( v == NULL ) {
/**/
}
v->pos = (Point3*)malloc( sizeof(Point3) );
if( v->pos == NULL ) {
/**/
}
v->direction = (Point3*)malloc( sizeof(Point3) );
if( v->direction == NULL ) {
/**/
}
return v;
}
And then use it, when you need new Vector.
Vector* v = allocate_vector( );

Related

Incorrect pointer created within a function

I'm trying to implement an integer vector in C. The vector pointer created in vector_copy is aroung 0x3 or 0x2, which causes segmentation fault. Why is that happenning?
This really baffles me since I have a similar implementation for vector_new.
typedef struct vector {
int* items;
size_t size;
size_t max;
} vector;
vector* vector_copy(vector* v) {
vector* v2;
memcpy(v2->items,v->items,v->max * sizeof(int*));
if (v2->items == NULL) {
return NULL;
}
v2->size = v->size;
v2->max = v->max;
return v2;
}
vector* vector_new(size_t initial_capacity) {
vector* newv;
newv->items = malloc(initial_capacity * sizeof(int*));
if (newv->items == NULL) {
return NULL;
}
newv->size = 0;
newv->max = initial_capacity;
return newv;
}
int main() {
vector* v;
vector* v2;
v = vector_new(4);
//new vector with capacity 4 and size 0
vector_push(v, 1);
vector_push(v, 2);
//1 and 2 are pushed back
v2=vector_copy(v);
//vector is supposed to be copied
vector_free(v);
vector_free(v2);
return 0;
}
vector* v2;
memcpy(v2->items,v->items,v->max * sizeof(int*));
This is not a good idea. You have basically created a pointer v2 that points to some arbitrary location (because you haven't initialised it), with the v2 pointer value probably being whatever was left over on the stack from some previous operation(a). Then, by copying bytes to that arbitrary location, all sorts of weirdness may ensue.
You need to actually allocate some memory for this new vector, with something like:
vector *v2 = vector_new(v->max);
memcpy(v2->items, v->items, v->max * sizeof(int));
You'll (hopefully) also notice I've changed the sizeof to use int rather than int*. I suspect that items points to an array of the former in which case that's the correct value to use.
So the following function is a better starting point:
vector *vector_copy(vector* v) {
// Use vector_new to get empty one with exact same properties.
vector *v2 = vector_new(v->max);
if (v2 == NULL) return NULL;
// Copy data in to it and return.
memcpy(v2->items, v->items, v->max * sizeof(int));
v2->size = v->size;
return v2;
}
You also have the exact same issues (no structure allocation and wrong sizeof) in your new function, which can be fixed with:
vector *vector_new(size_t initial_capacity) {
// Allocate a vector structure, fail if no go.
vector *newv = malloc(sizeof(vector));
if (newv == NULL) return NULL;
// Allocate the data area, free structure and fail if no go.
newv->items = malloc(initial_capacity * sizeof(int));
if (newv->items == NULL) {
free(newv);
return NULL;
}
// Set up everything needed and return it.
newv->size = 0;
newv->max = initial_capacity;
return newv;
}
The fact that this function sets the maximum based on initial_capacity relieves you of the necessity of setting max in vector_copy().
(a) I state "probably" because of the way many implementations work in terms of reusing stack frame memory regions. However, it's by no means guaranteed, just one possibility. You should just assume that it will have some random value and will therefore behave appropriately (or inappropriately, depending on your viewpoint).

C assign value to double pointer

I am working on some C code on micro processor stm32f103. Since allocating memory from the heap isn't stable, I am not encouraged to use the C library functions malloc() and free() etc. Instead, I thought of declaring a large chunk of static memory in advance during compilation time, and reallocating the memory to suit my pseudo dynamic memory allocation purposes. My new malloc implementation works fine when testing on my computer, but crashes on the stm32 when I do malloc for double data type.
Here is my malloc implementation. I know it is not a real dynamic memory allocation, but i do it just to practice using pointers.
pk_malloc.c
#include "pk_malloc.h"
char pool[RESERVE];
void* alloc[RESERVE];
void mem_init()
{
for (int i = 0; i != RESERVE; i++)
{
alloc[i] = NULL;
}
}
void* mem_malloc(size_t size)
{
if (size > 0)
{
for (int i = 0; i != RESERVE; i++)
{
if (alloc[i] == NULL)
{
int end;
for (end = i; end != RESERVE; end++)
{
if (alloc[end] != NULL || end - i == size + 1)
{
break;
}
}
if (end - i == size + 1)
{
for (int k = i + 1; k != end; k++)
{
alloc[k] = &pool[k];
}
return alloc[i + 1];
}
}
}
}
return NULL;
}
void* mem_realloc(void* mem, size_t new_size)
{
if (mem == NULL)
{
return mem_malloc(new_size);
}
int old_size = 0;
void** alloc_t = &alloc[(char*)(mem) - pool];
while (*alloc_t != NULL)
{
old_size++;
alloc_t++;
}
if (new_size <= old_size)
{
mem_free((char*)mem + new_size);
return mem;
}
else
{
int i = alloc_t - alloc;
int size = new_size - old_size;
int end;
for (end = i; end != RESERVE; end++)
{
if (alloc[end] != NULL || end - i == size + 1)
{
break;
}
}
if (end - i == size + 1)
{
for (int k = i; k != end - 1; k++)
{
alloc[k] = &pool[k];
}
return alloc[i];
}
else
{
void* realloc_t = mem_malloc(new_size);
if (realloc_t == NULL)
{
return mem;
}
else
{
mem_copy(realloc_t, mem);
mem_free(mem);
return realloc_t;
}
}
}
}
void mem_copy(void* dest, void* source)
{
int dest_index = (char*)(dest) - pool;
int source_index = (char*)(source) - pool;
char* writer = (char*)(source);
while (alloc[source_index] != NULL && alloc[dest_index] != NULL)
{
pool[dest_index] = pool[source_index];
dest_index++;
source_index++;
}
}
void mem_free(void* mem)
{
if (mem != NULL)
{
void** alloc_t = &alloc[(char*)(mem) - pool];
while (*alloc_t != NULL)
{
*alloc_t = NULL;
alloc_t++;
}
}
}
pk_malloc.h
#ifndef _PK_MALLOC
#define _PK_MALLOC
#include <stdlib.h>
#define RESERVE 64
void mem_init();
void* mem_malloc(size_t size);
void* mem_realloc(void* mem, size_t new_size);
void mem_copy(void* dest, void* source);
void mem_free(void* mem);
#endif
main.c
int main()
{
mem_init();
int* hoho = (int*)(mem_malloc(sizeof(int)));
*hoho = 123;
printf("%d", *hoho);
mem_free(hoho);
}
The code works on my computer, and also works on the STM32. However when I change my datatype to a double:
int main()
{
mem_init();
double* hoho = (double*)(mem_malloc(sizeof(double)));
*hoho = 0.618;
printf("%f", *hoho);
mem_free(hoho);
}
It only works on my computer, while it crashed on the STM32.
I did some testing and debugs, I find that this line works, the pointer is not NULL and it has a valid address.
double* hoho = (double*)(mem_malloc(sizeof(double)));
However this line crashed.
*hoho = 0.618;
After more testing, I find any data types occupying more than 4 bytes crashes the same way, including long long etc.
Strangely, I made some user defined structs with lots of int, float data types etc, which definitely occupies more than 4 bytes, the code works fine on the STM32.
struct ABC
{
int a;
float b;
};
This line works no problems.
struct ABC* hoho = (struct ABC*)(mem_malloc(sizeof(struct ABC)));
The variable hoho can be assigned, and its members can be accessed without ease, working both on my computer and the STM32.
Please note that all the code works on my laptop, and most data types work for the STM32 too.
I have been stuck with the problem for hours, any help appreciated.
The core in STM32F1 is a Cortex-M3. This QA here points out that while unaligned word access is allowed by Cortex-M3 for simple instructions, not all instructions support unaligned access. In your case, the C compiler uses an instruction that doesn't support an unaligned address with double.
Notice that
the standard library malloc returns a pointer that is "suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated" (C11 7.22.3)
while a pointer may be converted to another pointer, "if the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined" (C11 6.3.2.3p7).
Thus the behaviour of a program is undefined already at these lines
int *hoho = mem_malloc(sizeof(int));
double *hoho = mem_malloc(sizeof(double));
if the pointer returned is not suitably aligned for int and double respectively.
To fix the code, change it so that it always returns pointers of proper alignment. The official ARM compilers maintain an 8-byte aligned heap.

Getting a seg fault when trying to append a point in 3D space to the end of an array

I have a function which appends a point in 3D space to the end of an array and then it calculates the time that it takes to append each point. But when I ran my code, it created an initialized the code fine. But when it tried to run the function append, it just seg faulted right away. I've been looking at my code but I can't figure out why it seg faulted. Can anybody help me out?
This is my append code:
int point_array_append( point_array_t* pa, point_t* p)
{
assert( pa );
assert( p );
if( pa->len < pa->reserved )
{
size_t new_res = pa->len * 2 + 1; // add 1 to take care of a NULL array
size_t sz= new_res * sizeof(point_t);
point_t* tmp = realloc( pa->points, sz );
if( tmp == 0 )
return 1; //fail
pa->points = tmp;
pa->reserved = new_res;
}
pa->points[pa->len] = *p; // copy struct into array
pa->len++;
return 0;
}
These are the two structs I use:
typedef struct point
{
double x, y, z; // location in 3D space
} point_t;
typedef struct
{
size_t len; // number of points in the array
point_t* points; // an array of len point_t structs
size_t reserved;
} point_array_t;
Probably you might have a bug in the if condition:
if( pa->len < pa->reserved )
What you probably want is:
if ( <there are no more free slots in the array> )
reallocate
which translates to:
if (pa->len >= pa->reserved)
... do the reallocation

Want to reduce a function by looping through structs

Good Morning All,
I'm trying to reduce a function that's very repetitive, but each "repetition" has two structs with struct A.element1 setting struct B.element1. At the moment I have myFunction() with about twelve different reqFunction() calls to set B to A. Basically what I have now is:
void myFunction( structB *B )
{
structA A;
if( reqGetFunction( GLOBAL_IN_1, ( void *)&A, SIZE ) != 0 )
{
A.element3 = -1;
printf( "element3 failed\n" );
}
B->element7 = A.element3; // A is gotten when regGetFunction() is called
.
.
.
if( reqGetFunction( GLOBAL_IN_12, ( void *)&A, SIZE ) != 0 )
{
A.element14 = -1;
printf( "element14 failed\n" );
}
B->element18 = A.element14;
}
reqGetFunction() can't be changed. I have a static global array for other functions that would loop through GLOBAL_IN, and I could make structA A a static global.
I want to have something like myFunctionSingle() that will do one block, and myFunctionAll() that will have a for loop to cycle through the GLOBAL_IN array as well as the elements of struct's A and B and input them to myFunctionSingle().
So I guess my real question is how could I cycle through the elements of the structs as I can with an array, because everything there (like the structs' setups and reqGetFunction) are set in stone. I've tried a few things and searched around, but am currently stumped. I'm honestly not sure if this is possible or even worth it. Thank you in advance for your input!
Your function calls differ by 1)GLOBAL_IN_XX values 2)A.elementxx that you modify. 3)B.elementxx that you modify
What you need to do is to create a struct containing a value for GLOBAL_IN_XX a pointers to A.element and B.element, whatever type they are, for example:
struct call_parms
{
int global_parm;
int* a_ptr;
int* b_ptr;
};
Then, you need to create an array of those and initialize it accordingly, for example:
struct call_parms callParmsArray[MAX_CALLS]= {{GLOBAL_IN_1,&A.element3,&(B->element5)}, ... };
Then, just iterate over array and call your reqGetFunction with the parameters specified in each array element,something along the lines of:
for(int i = 0; i<MAX_CALLS;i++)
{
reqGetFunction( callParmsArray[i].global_parm, callParmsArray[i].element_ptr, SIZE );
}
You may also want factor a pointer to B->element in the struct and deal with it accordingly, as it is also repetitive. This will likely involve creating a wrapper around reqGetFunction() which will also deal with B and such:
struct call_parms
{
int global_parm;
int* a_ptr;
int* b_ptr;
};
bool myReqFn(struct call_parms* parm)
{
bool res;
if( res = reqGetFunction( parm->global_parm, ( void *)&A, SIZE ) != 0 )
{
*(parm->a_ptr) = -1;
printf( "element %d failed\n",parm->global_parm );
}
*(parm->b_ptr) = *(parm->a_ptr);
return res;
}
for(int i = 0; i<MAX_CALLS;i++)
{
myReqFn( &callParmsArray[i]);
}
The rest is left as an exercise to the reader, as they say...
One way to cycle through a struct that I know of is to use pointer math. I'm not sure what kind of datatype your struct members are, but if you have a concurrent set of identical datatypes numbered from j to k, your code would look something like this:
(_datatype_)*a = &(A.elementj);
(_datatype_)*b = &(B.elementj);
int i;
for (i = j; i < k; i++)
{
*(b + ((_sizeofdatatype) * (i - j)) = *(a + ((_sizeofdatatype) * (i - j));
}
EDIT: This is also, of course, assuming that you want to duplicate each pair of corresponding elements in order, but you can probably tweak it around to get the desired effect.
EDIT: This also assumes you allocate your entire struct (including variables) at the same time, so be careful.
Does GLOBAL_IN_XXX mean GLOBAL_IN[XXX] etc? And does GLOBAL_IN_XXX always map to A.element(XXX+2)? And its always B.element(N+1) = A.elementN?
I'm also going to assume that you can't change A.element1, A.element2 into A.element[], otherwise the soution would be fairly simple wouldn't it?
The most portable solution is to know the offset of each element in A and B (in case there are data alignment gotchas in the stuctures... could occur if you don't have N consecutive ELEMENT_TYPES etc)
#include <stddef.h>
// NOTE: These arrays are clumbsy but avoid making assumptions about member alignment
// in strucs.
static size_t const A_Offsets[] = {
offsetof(struct A, element1),
offsetof(struct A, element2),
offsetof(struct A, element3),
...
...
offsetof(struct A, elementN) };
static size_t const B_Offsets[] = {
offsetof(struct B, element1),
offsetof(struct B, element2),
offsetof(struct B, element3),
...
...
offsetof(struct B, elementN) };
void myFunctionSingle( structB *B, unsigned int index )
{
structA A;
ELEMENT_TYPE *elAPtr = (ELEMENT_TYPE *)((char *)A + A_Offsets[index + 2]);
ELEMENT_TYPE *elBPtr = (ELEMENT_TYPE *)((char *)A + B_Offsets[index + 6]);
if( reqGetFunction( GLOBAL_IN[index], ( void *)&A, SIZE ) != 0 )
{
*elAPtr = -1;
printf( "element%u failed\n", index);
}
*elBPtr = *elAPtr; // A is gotten when regGetFunction() is called
}
void myFunction( structB *B )
{
unsigned int i = 1;
for(; i < MAX_INDEX; ++i)
myFunctionSingle(B, i);
}
EDIT: I'm not sure if the offsetof() stuff is necessary because if you structure has only ELEMENT_TYPE data in it they are probably packed tight, but I'm not sure... if they are packed tight, then you don't have any data alignment issues so you could use the solution presented in Boston Walker's answer.

"dynamic array of static arrays"

How do you specify a dynamic array of static arrays in C?
I want to make a struct holding two dynamic arrays of static arrays.
struct indexed_face_set {
double * [3] vertices;
int * [3] faces;
};
This should hold a dynamic list of vertices, which are each 3 doubles, and a dynamic list of faces, which are each 3 ints.
The syntax is, well, C's approach to declarations is not the cleanest and C++ inherited that...
double (*vertices)[3];
That declaration means that vertices is a pointer to double [3] objects. Note that the parenthesis are needed, otherwise (as in double *vertices[3]) it would mean an array of 3 double*.
After some time you end up getting use to the inverted way of parenthesis on expressions...
For the specific case of a structure containing two arrays each of dimension 3, it would be simpler to make the arrays a part of the structure, rather than dynamically allocating them separately:
struct indexed_face_set
{
double vertices[3];
int faces[3];
};
However, there certainly could be cases where it makes sense to handle dynamic array allocation. In that case, you need a pointer to an array in the structure (and not an array of pointers). So, you would need to write:
struct indexed_face_set
{
double (*vertices)[3];
int (*faces)[3];
};
To allocate a complete struct indexed_face_set, you need to use something like new_indexed_face_set() and to free one you need to use something like destroy_indexed_face_set():
struct indexed_face_set *new_indexed_face_set(void)
{
struct indexed_face_set *new_ifs = malloc(sizeof(*new_ifs));
if (new_ifs != 0)
{
double (*v)[3] = malloc(sizeof(*v));
int (*f)[3] = malloc(sizeof(*f));
if (v == 0 || f == 0)
{
free(v);
free(f);
free(new_ifs);
new_ifs = 0;
}
else
{
new_ifs->vertices = v;
new_ifs->faces = f;
}
}
return(new_ifs);
}
void destroy_indexed_face_set(struct indexed_face_set *ifs)
{
if (ifs != 0)
{
free(ifs->vertices);
free(ifs->faces);
free(ifs);
}
}
Then you can use it like this:
void play_with_ifs(void)
{
struct indexed_face_set *ifs = new_indexed_face_set();
if (ifs != 0)
{
(*ifs->vertices)[0] = 3.14159;
(*ifs->vertices)[1] = 2.71813;
(*ifs->vertices)[2] = 1.61803;
(*ifs->faces)[0] = 31;
(*ifs->faces)[1] = 30;
(*ifs->faces)[2] = 29;
do_something_fancy(ifs);
destroy_indexed_face_set(ifs);
}
}
Note that the notation using pointers to arrays is moderately messy; one reason why people do not often use them.
You could use this fragment as the body of a header:
#ifndef DASS_H_INCLUDED
#define DASS_H_INCLUDED
struct indexed_face_set;
extern void play_with_ifs(void);
extern void do_something_fancy(struct indexed_face_set *ifs);
extern void destroy_indexed_face_set(struct indexed_face_set *ifs);
extern struct indexed_face_set *new_indexed_face_set(void);
#endif /* DASS_H_INCLUDED */
It doesn't need any extra headers included; it does not need the details of the structure definition for these functions. You'd wrap it in suitable header guards.
Because the code above is a bit messy when it comes to using the arrays, most people would use a simpler notation. The header above can be left unchanged, but the code could be changed to:
struct indexed_face_set
{
double *vertices;
int *faces;
};
struct indexed_face_set *new_indexed_face_set(void)
{
struct indexed_face_set *new_ifs = malloc(sizeof(*new_ifs));
if (new_ifs != 0)
{
double *v = malloc(3 * sizeof(*v));
int *f = malloc(3 * sizeof(*f));
if (v == 0 || f == 0)
{
free(v);
free(f);
free(new_ifs);
new_ifs = 0;
}
else
{
new_ifs->vertices = v;
new_ifs->faces = f;
}
}
return(new_ifs);
}
void destroy_indexed_face_set(struct indexed_face_set *ifs)
{
if (ifs != 0)
{
free(ifs->vertices);
free(ifs->faces);
free(ifs);
}
}
void play_with_ifs(void)
{
struct indexed_face_set *ifs = new_indexed_face_set();
if (ifs != 0)
{
ifs->vertices[0] = 3.14159;
ifs->vertices[1] = 2.71813;
ifs->vertices[2] = 1.61803;
ifs->faces[0] = 31;
ifs->faces[1] = 30;
ifs->faces[2] = 29;
do_something_fancy(ifs);
destroy_indexed_face_set(ifs);
}
}
This is much simpler to understand and use and would generally be regarded as more idiomatic C.
Since the size of each array is fixed, there's no particular need to record the size in the structure. If the sizes varied at runtime, and especially if some indexed face sets had, say, 8 vertices and 6 faces (cuboid?), then you might well want to record the sizes of the arrays in the structure. You'd also specify the number of vertices and number of faces in the call to new_indexed_face_set().

Resources