Constructor for structs in C - c

Given:
struct objStruct {
int id;
int value;
};
typedef struct objStruct Object;
Is there a shortcut to allocate and initialize the object, something like a C++ constructor?
It could even be a preprocessor macro. Whatever makes the code shorter and more readable than this:
Object *newObj = malloc(sizeof(Object));
// successful allocation test snipped
newObj->id = id++;
newObj->value = myValue;

In C I typically create a function in the style of a constructor which does this. For example (error checking omitted for brevity)
Object* Object_new(int id, int value) {
Object* p = malloc(sizeof(Object));
p->id = id;
p->value = value;
return p;
}
...
Object* p1 = Object_new(id++, myValue);

In C99 and beyond, you can use a compound literal, which looks like a cast followed by an initializer in braces:
int init_value = ...;
int init_id = ...;
Object newObj1 = (Object){ .value = init_value, .id = init_id };
Object newObj2 = (Object){ .id = init_id, .value = init_value };
The latter two lines achieve the same effect - the order of the fields is not critical. That is using 'designated initializers', another C99 feature. You can create a compound literal without using designated initializers.

In C it is possible to declare an inline function with the same name as structure:
struct my
{
int a;
};
inline struct my* my(int* a)
{
return (struct my*)(a);
}
//somewhere in code
int num = 123;
struct my *sample = my(&num);
//somewhere in code
It looks pretty similar to C++ ctors.

struct thingy {
char * label;
int x;
};
#define declare_thingy( name, label, val) struct thingy name = { label, val }
struct thingy * new_thingy(const char * label, int val) {
struct thingy * p = malloc(sizeof(struct thingy));
if (p) {
p->label = label;
p->val = val;
}
return p;
}

You really have to distinguish initialization of static or auto variables and dynamic allocation on the head. For the first, do named initializers, for the second a well specified init function.
All that can be nicely
packed into macros do give you an easy static/auto intialization and something similar to new in C++.

If you are looking for an object oriented "emulation" over C, I strongly recommend the GObject Type System [1], it's mature and largely used by GTK for instance.
GLib [2] has also a nice slice allocator for small objects, currently used by GNOME.
[1] GObject Reference Manual
[2] GLib Memory Slices

Related

Is it proper to initialize variables in a structure define in typedef (C programming)

typedef struct
{
int id = 0;
char *name = NULL;
char *department = NULL;
int phone = 0;
} emp;
In C programming is it a good programming practice to do something like that, or, should I initialize when I declare the variable 'emp'.
I am using a GCC compiler and the above code does compile. I want to know if it is the proper way of initializing.
With typedef struct { ... } emp; you are creating a new complex type called "emp". When you declare a variable of type "emp", that is where you typically initialize it.
I would go with:
typedef struct
{
int id;
char *name;
char *department;
int phone;
} emp;
emp myVar = {
/* id */ 0,
/* name */ NULL,
/* department */, NULL,
/* phone */ 0
};
Since the syntax you show won't compile in a C compiler — nor a C++ compiler, AFAIK — you don't have any choice in the matter. You can't do what you are trying to do and must initialize when you declare a variable of type emp.
Better to initialize when you declare emp
In plain C, you can't give default values to struct members. If it's useful to create it with some default values, you could write a function like this:
void emp_set_defaults(emp *e)
{
assert(e != NULL);
e->id = 0;
e->name = NULL;
e->department = NULL;
e->phone = 0;
}
and use it like
emp e;
emp_set_defaults(&e);
In C99 you can use designated initializers to create a struct object with its members filled in by name. Here's an example:
emp myVar = {
.id = 0,
.name = NULL,
.department = NULL,
.phone = 0
};
More info at C struct initialization using labels. It works, but how? Documentation?

Referencing a struct within a struct

I have a C struct generated by an external tool. It looks like this:
typedef struct externalStruct{
int msgID;
struct internalStruct {
long someValue;
} *internalStruct ;
} externalStruct_t;
Do the following leaves internalStruct pointed to some random value on the heap:
externalStruct_t* newExternalStruct = new externalStruct_t;
So here's my question:
How do I properly instantiate the pointer "internalStruct"?
Here is how you can do it in C (C99 demo):
externalStruct_t* newExternalStruct = malloc(sizeof(externalStruct_t));
newExternalStruct->internalStruct = malloc(sizeof(*newExternalStruct->internalStruct));
In C++ you would need to insert casts (C++ demo):
externalStruct_t* newExternalStruct = new externalStruct_t;
// You need to rename internalStruct to internalStructType
// to avoid a naming collision:
newExternalStruct->internalStruct = new externalStruct::internalStructType;

Is it possible to return a pointer to a struct without using malloc?

I'm writing a Gameboy ROM using the GBDK, which has an unstable version of malloc that I'm unable to get working. I'm also unable to return a struct within a struct. That leaves me trying to return a pointer, which is why I'm wondering if there is a way to avoid using malloc when returning a struct pointer?
What I'm basically trying to do is that I want to be able to write something like this:
create_struct(struct_name, char member_x, char member_y);
This is the code I have written using malloc:
struct point {
char member_x;
char member_y;
};
struct point *makepoint(char member_x, char member_y) {
struct point *temp = malloc(sizeof(struct point));
temp->member_x = member_x;
temp->member_y = member_y;
return temp;
};
There are various valid ways to return a pointer (to a struct, or any type of object), but the only way to return a pointer to a new object that didn't exist before the function was called is to use malloc, realloc, calloc, aligned_alloc (C11), or some implementation-defined allocation function (e.g. mmap on POSIX systems, etc.).
Other ways you could return a valid pointer include:
A pointer to an object with static storage duration. Only once instance of such an object exists, so this is usually a bad way.
A pointer that was passed to the function as an argument for use as a place to store the result. This can often be a good approach, since you pass off responsibility for obtaining the storage to the caller.
A pointer to an object obtained from some sort of global pool. This could be a very good approach in embedded systems and game design for low-end gaming devices.
Is it possible to return a pointer to a struct without using malloc?
I. Technically, yes. You can make your struct static so that it survives function calls:
struct foo *bar()
{
static struct foo f = { 1, 2, 3 };
return &f;
}
But I doubt you actually want to do this (since this has funny side effects, read up on the meaning of the static keyword). You have several different possibilities:
II. The approach what the C standard library takes is always making the caller implicitly responsible for providing the struct and managing memory. So instead of returning a pointer, the function accepts a pointer to struct and fills it:
void dostuff(struct foo *f)
{
foo->quirk = 42;
}
III. Or return the struct itself, it doesn't hurt, does it (it can even be move-optimized):
struct foo bar()
{
struct foo f = { 1, 2, 3 };
return f;
}
So, choose your poison.
just do something like:
void makepoint(struct point *dest, char member_x, char member_y) {
dest->member_x = member_x; // you had these wrong in your code, by the way
dest->member_y = member_y;
}
The structure will need to be "allocated" elsewhere (probably on the stack is your best bet).
You could pass the struct as a parameter and have the function initialize it :
struct point *makepoint(struct point *pt, char x, char y) {
pt->x = x;
pt->y = y;
return pt;
}
and then call it like this :
struct point pt;
makepoint(&pt, 'a', 'b');
but then you might as well just have done :
struct point pt = { 'a', 'b' };
Note that in this case (struct point only occupies 2 bytes) you can return struct point instead of struct point *, (this should not be done with large structs)
#include <stdio.h>
struct point {
char member_x;
char member_y;
};
struct point makepoint(char member_x, char member_y)
{
struct point temp;
temp.member_x = member_x;
temp.member_y = member_y;
return temp;
}
int main(void)
{
struct point t = makepoint('a', 'b');
printf("%c %c\n", t.member_x, t.member_y);
return 0;
}
If it is not possible to get malloc() fixed, then you may just want to manage your own pre-allocated points, and limit the number of points that can be "created". You would need to alter your points a little to allow for easier management:
union free_point {
union free_point *next;
struct point data;
};
union free_point free_point_pool[MAX_POINTS];
union free_point *free_point_list;
struct point *makepoint(char member_x, char member_y) {
static int i;
union free_point *temp;
temp = 0;
if (i == MAX_POINTS) {
if (free_point_list) {
temp = free_point_list;
free_point_list = temp->next;
}
} else {
temp = free_point_pool + i++;
}
if (temp) {
temp->data.x = x;
temp->data.y = y;
}
return &temp->data;
};
Then, instead of calling free() on the result returned by makepoint(), you should create a new function to place it on the free_point_list.
void unmakepoint (struct point *p) {
union free_point *fp = (union free_point *)p;
if (fp) {
fp->next = free_point_list;
free_point_list = fp;
}
}
The simplest thing is just to return a structure that has been created using named initializers, and do so in an inline function, so that there is zero overhead:
static inline struct point makepoint(char x, char y) {
return (struct point) { .x = x, .y = y };
}
Then you can call it like this:
struct point foo = makepoint(10, 20);
Couldn't be simpler!

void pointers and function pointers in structure members

Hello I have following code.
typedef struct __vector {
int (*container_end) ( struct __vector *);
}vector;
and another iterator structure with following declaration :
typedef struct __iterator {
void *ptr_to_container;
int (*end)(struct __iterator *);
}iterator;
int
end(iterator *itr) {
return (itr->ptr_to_container)->container_end(itr->ptr_to_container);
}
This code does not compile as ptr_to_container is void pointer.
Is there any work-around to this problem.
container_end function will be defined separately and ptr_to_container will point to some container.
thanks
Avinash
It looks like you have missed something when defining the iterator structure. Why does the iterator have a function pointer to an 'end' function that accepts an iterator?
If you want it to be really generic, you could perhaps use this definition instead:
typedef struct __iterator {
void * ptr_to_container;
int (*end)(void *);
} iterator;
int end(iterator * it) { return it->end(it->ptr_to_container)); }
In the vector definition (and other data types), you can then define a function to create an iterator:
static int vector_end(vector * v) { /* implementation omittted */ }
iterator * vector_create_iterator(vector * v)
{
iterator * it = malloc(sizeof(iterator));
it->ptr_to_container = v;
it->end = vector_end;
return it;
}
However, the solution really depends on how the data structures are defined. In the above suggestion, it is up to each data structure to provide an implementation for how to traverse it.
As an alternative, you could set up a generic data structure interface, like
typedef struct _container container;
struct _container {
int (*end)(container * c);
};
Then the vector implementation would "only" have to fill in this container structure:
typedef struct _vector {
container c;
/* other fields required by the vector */
}
static int vector_end(container * c)
{
vector * v = (vector *) c;
...
}
container * create_vector()
{
vector * v = malloc(sizeof(vector));
v->c.end = vector_end;
return v;
}
...and the iterator could work with just the generic container:
typedef struct _iterator {
container * c;
/* other fields used by the iterator, such as current position */
}
int end(iterator * it) { return it->c->end(it->c); }
From the code sample in the question, it looks almost like you have mixed up these two approaches :-)
Did you try casting to a vector *?
return ((vector *)(itr->ptr_to_container))->containter_end(itr->ptr_to_container);
However, are you sure you want to do this? You are using itr to call a function and then pass itr to that function. Including more context (more code) would help.
You need to explicitly cast *ptr_to_container to a vector pointer:
((__vector *)(itr->ptr_to_container))->container_end
Otherwise the compiler doesn't know what is the structure of the target.
Though, I don't really see why you want to have such a construction. It looks like you want to have object orientation here with inheritance, but without explicitly stating anything. It won't work well. In C, you'll have to use less general structures, or move to C++.
If it must be void * use
int
end(iterator *itr) {
return ((vector)(itr->ptr_to_container))->container_end(itr->ptr_to_container);
}
or else specify in the iterator that it is a vector iterator
typedef struct __iterator {
vector *ptr_to_container;
int (*end)(struct __iterator *);
}iterator; //probably you'll need to rename to make type of iterator clear
If you need to keep the abstraction (one iterator for all of you containers) nothing comes to mind atm...

C Struct initialization : strange way

While reading a code I came across, the following definition and initialization of a struct:
// header file
struct foo{
char* name;
int value;
};
//Implementation file
struct foo fooElmnt __foo;
// some code using fooElmnt
struct foo fooElmnt __foo = {
.name = "NAME";
.value = some_value;
}
What does this mean in C and how is it different from usual declarations?
It's called designated initialization,
In a structure initializer, specify
the name of a field to initialize with
.fieldname = before the element
value. For example, given the
following structure,
struct point { int x, y; };
the following initialization
struct point p = { .y = yvalue, .x = xvalue };
is equivalent to
struct point p = { xvalue, yvalue };
If you read on, it explains that .fieldname is called a designator.
UPDATE: I'm no C99 expert, but I couldn't compile the code. Here's the changes I had to make:
// header file
struct foo{
char* name;
int value;
};
//Implementation file
//struct foo fooElmnt __foo;
// some code using fooElmnt
struct foo fooElmnt = {
.name = "NAME",
.value = 123
};
Were you able to compile it? I used TCC.
Those are designated initializers, introduced in c99. You can read more here
Without them, you'd use
struct foo fooElmnt __foo = {
"NAME",
some_value
};
While in this case it doesn't matter much - other than the c99 way is more verbose, and its easier to read which element is initialized to what.
It does help if your struct has a lot of members and you only need to initialize a few of them to something other than zero.
This is a designated initialization. This also initializing the fields by their name, which is more readable than anomynous initialization when the structures are getting large. This has been introduced by the C99 standard.

Resources