What is the data type of the name of a struct - c

If I wanted to make a function which takes the name of a struct as an argument, what would the method signature look like?
typedef struct Class{
} Class;
main()
{
Class *a = malloc(Class);
return instanceOf(a, Class);
}
What would the declaration of instanceOf look like?

You can't pass types to functions in C. However, you can simulate this behaviour using macros:
#define new_instance(t) (malloc(sizeof(t)))
Class *instance = new_instance(Class);

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define type(x) #x
typedef struct Class{
char* type;
} Class;
Class *Class_new(){
Class *v;
v=(Class*)malloc(sizeof(Class));
v->type = "Class";
return v;
}
void Class_free(Class *a){
free(a);
}
int instanceOf(Class *a, const char* type){
return strcmp(a->type, type) == 0;
}
int main(){
Class *a = Class_new();
printf("%s\n", instanceOf(a, type(Class)) ? "YES" : "NO");
Class_free(a);
return 0;
}

// Encode and encapsulate the type within a nested structure when you create it.
struct struct_info
{
int type;
char name[32];
}
struct mystruct
{
struct struct_info;
}

Related

How to pass the variable address of the structure short name to a function

How can I pass the variable address of the structure short name (color) to a function (fun) arguments.
#include <stdio.h>
void fun();
struct figure {
char name[30];
float field;
} color;
int main(void) {
fun();
return 0;
}
How to pass the variable address of the structure short name
To pass the address you only need &color.
Then the function needs to accept a pointer to struct figure.
It may look like:
#include <stdio.h>
#include <string.h>
struct figure{
char name[30];
float field;
} color;
void fun(struct figure *); // Function takes pointer to struct figure
int main(void){
strcpy(color.name, "Joe"); // Initialize color
color.field = 42.0;
fun(&color); // Pass address of color
return 0;
}
void fun(struct figure *c)
{
printf("%s\n", c->name); // Access color using the passed pointer
printf("%f\n", c->field);
}
Output:
Joe
42.000000
struct figure { ... }; would just introduce a new type named struct figure, whereas struct figure { ... } color; does two things (1) introduce above mentioned type and (2) define a variable named color of that type.
To pass an object of type struct figure to a function, write...
struct figure{
char name[30];
float field;
} color;
void fun(struct figure f) {
printf("%s %f\n", f.name, f.field);
}
int main(void){
struct figure myObj;
strcpy(myObj.name, "Hello!");
myObj.field = 1.0;
fun(myObj);
return 0;
}
You could also pass the address of such an object, which would then allow the function to alter the originally passed object as well:
void fun(struct figure *f) {
f->field = 2.0
printf("%s %f\n", f->name, f->field);
}
int main() {
...
fun(&myObj);

Ways to illicit polymorphic properties in regular C?

Hi I am currently attempting to learn C and I was wondering if there is a way to attain polymorphism in structures which contain a list of other different type of structures?
An example case of this is as such:
#include <stdlib.h>
#include <stdio.h>
typedef void (*update_t)(void *);
typedef struct entity entity_t;
typedef struct compA compA_t;
typedef struct compB compB_t;
struct compA{
update_t update;
};
struct compB{
update_t update;
};
struct entity{
update_t update;
int curSize;
void **components;
};
void compA_update(void *c){
printf("updating: componentA\n");
}
compA_t *compA_create(){
compA_t *c = malloc(sizeof(compA_t));
c->update = compA_update;
return c;
}
void compB_update(void *c){
printf("updating: componentB\n");
}
compB_t *compB_create(){
compB_t *c = malloc(sizeof(compB_t));
c->update = compB_update;
return c;
}
void entity_update(void *en){
entity_t *e = (entity_t *)en;
for(int i = 0; i < e->curSize; i++){
//would like to somehow update all the components with one line just iterating through the array but does not seem possible
}
return;
}
entity_t *entity_create(){
entity_t *e = malloc(sizeof(entity_t));
e->curSize = 0;
e->update = entity_update;
calloc(32, sizeof(void *));
return e;
}
void add_component(entity_t *e, void *c){
printf("%d\n", e->curSize);
e->components[e->curSize] = c;
e->curSize++;
return;
}
int main(void){
entity_t *e = entity_create();
compA_t *a = compA_create();
compB_t *b = compB_create();
add_component(e, a);
add_component(e, b);
e->update(e);
return 0;
}
So far my approach to this problem has been solved with void pointer arrays of a tuple structure which contains a enum type which identifies the structure as well as the structure itself and then in a potential update function a fairly ugly switch statement has to be implemented with a case for each specific type.
Is there a better way to do this? As the switch approach will get fairly crazy pretty fast if there are a lot of different types within the array. which means one must explicitly add cases for each type and every case does exactly the same thing, which in this case is call a function pointer named "update".
You can try data polymorphism instead of function pointer. That is, different data produce different behavior, using the same code.
For example, a simple polymorphic behavior:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
typedef const char* ccstr;
typedef struct animal_attr_t
{
bool is_body_segmented;
float gill_completeness;
float lung_completeness;
} animal_attr_t;
typedef struct species
{
ccstr name, kingdom, domain;
animal_attr_t animal_attr[0];
} species;
void initialize_species_base(species *this, ccstr name, ccstr kingdom, ccstr domain)
{
this->name = name;
this->kingdom = kingdom;
this->domain = domain;
}
void initialize_animal_attr(animal_attr_t *this, bool is_body_segmented, float gill_completenss, float lung_completeness)
{
this->is_body_segmented = is_body_segmented;
this->gill_completeness = gill_completenss;
this->lung_completeness = lung_completeness;
}
void print_species(species*);
int main(int argc, char *argv[])
{
species *yeast = calloc(sizeof(species), 1);
assert(yeast);
initialize_species_base(yeast, "yeast", "fungus", "eukaryote");
print_species(yeast);
species *dog = calloc(sizeof(species) + sizeof(animal_attr_t), 1);
assert(dog);
initialize_species_base(dog, "dog", "animal", "eukaryote");
initialize_animal_attr(dog->animal_attr, true, 0.0f, 1.0f);
print_species(dog);
free(yeast);
free(dog);
}
void print_species(species *this)
{
printf("name = %s, kingdom = %s, domain = %s",
this->name, this->kingdom, this->domain);
if (strcmp(this->kingdom, "animal") == 0) {
animal_attr_t *ani_attr = this->animal_attr;
printf(", has %s, %f completeness of gill, %f completeness of lung",
ani_attr->is_body_segmented ? "segmented body" : "unsegmented body",
ani_attr->gill_completeness, ani_attr->lung_completeness);
}
printf(".\n");
}
yeast and dog is 2 completely different types, yet with species it is expressed in an unified way and print_species has polymorphic behavior.

Understanding OOPC, am I doing it right?

I followed Alex's book on object oriented programming using ansi c.
So far tried to model a very basic string class -
Here's the code:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "class.h"
#include "mystring.h"
extern const void *String_c;
int main() {
String *my = new(String_c, "A random string");
char *text = my->str(my);
printf("String contains %s of length %d", text, my->length(my));
delete(my);
free(text);
return 0;
}
class.h
#ifndef CLASS_H_
#define CLASS_H_
#include <stddef.h>
typedef struct {
size_t size;
void* (*ctor) (void* self, va_list *app);
void (*dtor) (void* self);
} Class;
void* new(const void *class, ...);
void delete(void *object);
#endif /* CLASS_H_ */
class.c
/*
* class.c
*
* Created on: 22-Mar-2014
* Author: nilesh
*/
#include <stdarg.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include "class.h"
void *new(const void *_class, ...) {
printf("\nCreating new\n");
const Class *class = _class;
void *p = calloc(1, class->size);
assert(p);
* (const Class **) p = class;
if(class->ctor) {
va_list ap;
va_start(ap, _class);
p = class->ctor(p, &ap);
va_end(ap);
}
return p;
}
void delete(void *object) {
printf("\nDelete\n");
const Class **class = object;
if(object && *class && (*class)->dtor)
(*class)->dtor(object);
free(object);
object = NULL;
}
mystring.h
#ifndef STRING_H_
#define STRING_H_
#include <stddef.h>
#include "class.h"
typedef struct string String;
struct _string;
struct string {
const Class *class;
struct _string *_;
int (*length) (String *self);
char* (*str) (String *self);
};
extern Class _string_class;
extern const void *String_c;
#endif /* STRING_H_ */
mystring.c
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "mystring.h"
struct _string {
char *data;
int length;
};
static int length(String *self) {
return self->_->length;
}
static char* str(String *self) {
char *ret = malloc(sizeof(char) * self->_->length);
memcpy(ret, self->_->data, sizeof(char)*self->_->length);
return ret;
}
void* ctor(void *_self, va_list *app) {
printf("\nConstructor called\n");
String *self = _self;
self->_ = malloc(sizeof(struct _string));
char *text = va_arg(*app, char *);
self->_->length = strlen(text);
self->_->data = malloc(sizeof(char) * self->_->length);
memcpy(self->_->data, text, sizeof(char) * self->_->length);
self->length = length;
self->str = str;
return self;
}
void dtor(void *_self) {
printf("\nDestructor called\n");
String *self = _self;
free(self->_);
free(self->_->data);
self->_->data = NULL;
}
Class _string_class = {sizeof(String), ctor, dtor};
const void *String_c = &_string_class;
I have one question:
Why does
Class *class = object
In delete not work, while
Class **class = object
Works?
Works in the sense, in former it doesn't call dtor, but calls length and in case of latter, the call to function is (*class)->dtor which works.
The short answer is that class is of type Class **; class->dtor would work only if class were of type Class *.
You're probably getting confused because of the double indirection, so here's a longer explanation:
Think about structures layout. Imagine you have a simple structure like so:
struct example {
int xpto;
char a[10];
}
If you call a function f() and pass it a pointer p to struct example, then f() is free to cast such a pointer to int *. Dereferencing such a pointer yields the same result as p->xpto. That is, p->xpto and *(int *) p are equivalent. This happens because structure components are layed out in increasing memory addresses. xpto is the first member, meaning it's at offset 0. In other words, for any pointer to struct example, the first sizeof(int) bytes at the address pointed to by p belong to xpto.
Your string structure was defined as:
struct string {
const Class *class;
struct _string *_;
int (*length) (String *self);
char* (*str) (String *self);
};
Which shows that at offset 0 of struct string there is a (read-only) pointer to Class. When you call delete(my) in main(), you are giving it a pointer to struct string - thus, the first sizeof(const Class *) bytes in the address pointed to by my are a pointer to a Class. Like we did in the example with struct example - where we casted p to a pointer to the first member - casting such a pointer to Class ** (first member is a Class *, so a pointer to the first member is of type Class **) gives direct access to the first field (and only the first).
Because of that, delete() casts the pointer you give it to a Class **, because by doing so, dereferencing such a pointer yields a Class *.
Why doesn't class->dtor() work? Because class is of type Class **, so, class->dtor, which is equivalent to (*class).dtor is invalid: *class is of type Class *, it's not a structure, and as such, there is no member named dtor. You must use (*class)->dtor, since that's the same as (*(*class)).dtor.

Forward declaration C

I have 2 header files api.h and impl.h
api.h is visible to outside files and will be included in other ".c" files. So api.h includes impl.h
api.h defines 2 structures
typedef struct
{
uint32_t att;
union
{
struct
{
void* buffer;
size_t length;
} x;
struct
{
int a, b;
} v;
} content;
}dummy;
and impl.h has some other structures and function def which uses this structure.
I tried forward declaration but it doesn't help me .
Please help .
Actually, your dummy is not a structure, but a typedef to an unnamed structure. Try naming the structure, you can then forward-declare it:
typedef struct sdummy dummy; // forward declaration
void foo(dummy *);
struct sdummy { ... }; // definition
Either reorder your code in api.h so the type declaration precedes the #include "impl.h" or give your (currently anonymous) structure itself a name like dummy, dummy_, dummy_s so you can add a forward declaration
typedef struct dummy_ dummy;
to impl.h.
If you want to hide the details of your struct then you have to define it in some .c file, let's say impl.c, so that it has internal linkage to that compilation unit. To use it you have to expose create, destroy, getter and setter functions. So a basic setup would look like this:
api.h with forward declaration for your struct
// forward declaration
typedef struct dummy* dummy_t;
// create / destroy / setter / getter (omitted)
dummy_t alloc_dummy();
void free_dummy(dummy_t);
void set_number(dummy_t, int);
void set_string(dummy_t, char*);
void print_dummy(dummy_t);
Then comes impl.c
#include "api.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct dummy {
int n;
char* s;
};
dummy_t alloc_dummy()
{
return malloc(sizeof(struct dummy));
}
void free_dummy(dummy_t dummy)
{
if(dummy) {
free(dummy->s);
free(dummy);
}
}
void set_number(dummy_t dummy, int n)
{
if(dummy) {
dummy->n = n;
}
}
void set_string(dummy_t dummy, char* s)
{
if(dummy && s) {
dummy->s = strdup(s);
}
}
void print_dummy(dummy_t dummy)
{
if(dummy) {
printf("%d, %s\n", dummy->n, dummy->s);
}
}
And finally the usage in some other C files, here main.c
#include "api.h"
int main(int argc, char** argv)
{
// struct dummy d; // error! type is unknown
// instead use the create function
dummy_t d = alloc_dummy();
// d->n = 1; // error! dereference of unknown type
// instead use the setter function
set_number(d, 1);
set_string(d, "Hello, world!");
print_dummy(d);
free_dummy(d);
return 0;
}
Ouput
1, Hello, world!

Initializing a Struct of a Struct

If I have a struct in C that has an integer and an array, how do I initialize the integer to 0 and the first element of the array to 0, if the struct is a member another struct so that for every instance of the other struct the integer and the array has those initialized values?
Initialisers can be nested for nested structs, e.g.
typedef struct {
int j;
} Foo;
typedef struct {
int i;
Foo f;
} Bar;
Bar b = { 0, { 0 } };
I hope this sample program helps....
#include <stdio.h>
typedef struct
{
int a;
int b[10];
}xx;
typedef struct
{
xx x1;
char b;
}yy;
int main()
{
yy zz = {{0, {1,2,3}}, 'A'};
printf("\n %d %d %d %c\n", zz.x1.a, zz.x1.b[0], zz.x1.b[1], zz.b);
return 0;
}
yy zz = {{0, {0}}, 'A'}; will initialize all the elements of array b[10] will be set to 0.
Like #unwind suggestion, In C all instances created should initialized manually. No constructor kind of mechanism here.
You can 0-initialize the whole struct with {0}.
For example:
typedef struct {
char myStr[5];
} Foo;
typedef struct {
Foo f;
} Bar;
Bar b = {0}; // this line initializes all members of b to 0, including all characters in myStr.
C doesn't have constructors, so unless you are using an initializer expression in every case, i.e. write something like
my_big_struct = { { 0, 0 } };
to initialize the inner structure, you're going to have to add a function and make sure it's called in all cases where the structure is "instantiated":
my_big_struct a;
init_inner_struct(&a.inner_struct);
Here is an alternative example how you would do things like this with object-oriented design. Please note that this example uses runtime initialization.
mystruct.h
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct mystruct_t mystruct_t; // "opaque" type
const mystruct_t* mystruct_construct (void);
void mystruct_print (const mystruct_t* my);
void mystruct_destruct (const mystruct_t* my);
#endif
mystruct.c
#include "mystruct.h"
#include <stdlib.h>
#include <stdio.h>
struct mystruct_t // implementation of opaque type
{
int x; // private variable
int y; // private variable
};
const mystruct_t* mystruct_construct (void)
{
mystruct_t* my = malloc(sizeof(mystruct_t));
if(my == NULL)
{
; // error handling needs to be implemented
}
my->x = 1;
my->y = 2;
return my;
}
void mystruct_print (const mystruct_t* my)
{
printf("%d %d\n", my->x, my->y);
}
void mystruct_destruct (const mystruct_t* my)
{
free( (void*)my );
}
main.c
int main (void)
{
const mystruct_t* x = mystruct_construct();
mystruct_print(x);
mystruct_destruct(x);
return 0;
}
You don't necessarily need to use malloc, you can use a private, statically allocated memory pool as well.

Resources