How can I store a function pointer in a structure? - c

I have declared typedef void (*DoRunTimeChecks)();
How do I store that as a field in a struct? How do I assign it? How do I call the fn()?

Just put it in like you would any other field:
struct example {
int x;
DoRunTimeChecks y;
};
void Function(void)
{
}
struct example anExample = { 12, Function };
To assign to the field:
anExample.y = Function;
To call the function:
anExample.y();

#include <stdio.h>
typedef void (*DoRunTimeChecks)();
struct func_struct {
DoRunTimeChecks func;
};
void function()
{
puts("hello");
}
int main()
{
struct func_struct func_struct;
func_struct.func = function;
func_struct.func();
return 0;
}

Related

Is it possible in C to have a struct or union of functions?

Is there any way, whether union, struct, or something else, to have a group of functions?
typedef struct {
//ERROR
int sqr(int i) {
return i * i;
}
//ERROR
int cube (int i) {
return i * i * i;
}
} test;
Fields in structs can be function pointers:
struct Interface {
int (*eval)(int i);
};
You cannot define the functions in the struct body, but you can assign functions with the same signature to the struct fields:
int my_sqr(int i) {
return i * i;
}
int my_cube(int i) {
return i * i * i;
}
struct Interface squarer = { my_sqr };
struct Interface cuber = { my_cube };
Then call the fields like a normal function:
printf("%d\n", squarer.eval(4)); // "16"
printf("%d\n", cuber.eval(4)); // "64"

How to get pointer address in function that called through this pointer

I read this article but it doesn't answer my question.
file: hero.h
typedef struct {
int id;
void (*setId)();
int (*getId)();
} Hero, *HeroPtr;
file: hero.c
#include "hero.h"
static void setId(int id);
Hero obj = {
.setId = setId,
.getId = getId,
};
void setId(int id) {
HeroPtr hero_obj = 0x0; //TODO how get address: hero_obj1 (1 > ) OR
// hero_obj2 (2 > )
hero_obj->id = id;
}
void getId() {
HeroPtr hero_obj = 0x0; //TODO how get address: hero_obj1 (1 > ) OR
// hero_obj2 (2 > )
return hero_obj->id;
}
file: main.c
#include "hero.h"
int main() {
Hero hero_obj1, hero_obj2;
//1 >
hero_obj1->setId(1);
//2 >
hero_obj2->setId(2);
return 0;
}
You could do the equivalent of what C++ does behind the scenes.
file: hero.h
typedef struct hero {
int id;
void (*setId)(struct hero*, int);
int (*getId)(struct hero*);
} Hero, *HeroPtr;
void constructHero(HeroPtr this);
file: hero.c
#include "hero.h"
static void setId(HeroPtr this, int id);
static int getId(HeroPtr this);
Hero initObj = {
.setId = &setId,
.getId = &getId,
};
void constructHero(HeroPtr this)
{
*this = initObj;
}
void setId(HeroPtr this, int id) {
HeroPtr hero_obj = this;
hero_obj->id = id;
}
int getId(HeroPtr this) {
HeroPtr hero_obj = this;
return hero_obj->id;
}
file: main.c
#include "hero.h"
#include "stdio.h"
int main() {
Hero hero1;
Hero hero2;
HeroPtr hero_obj1=&hero1;
HeroPtr hero_obj2=&hero2;
constructHero(hero_obj1);
constructHero(hero_obj2);
hero_obj1->setId(hero_obj1, 1);
hero_obj2->setId(hero_obj2, 2);
printf("hero_obj1 id = %d\n", hero_obj1->getId(hero_obj1));
printf("hero_obj2 id = %d\n", hero_obj2->getId(hero_obj2));
return 0;
}
It looks like you are trying to implement virtual functions in C, by using function pointers. In object-oriented programming languages like C++ or Java such functions or methods inside classes have an implicit this pointer as argument, which is hidden. That means that the int getId() function actually has the signature int getId(Hero* this) and the void setId(int id) function actually has the form void setId(Hero* this, int id). As I have already said, in object-oriented programming languages you don't see or add the this pointer and you also don't pass the argument when you invoke the function. The compiler does this for you. It always automatically passes the pointer to the instance as this pointer, on which the function was invoked. In C, however, these features don't exist. So you have to add the this argument and pass it when invoking the function by yourself.

Pointers to functions casting

I have the following structs:
struct mtmFlix_t {
List usersList;
List seriesList;
};
struct User_t {
int age;
char* username;
MtmFlix mtmFlix;
};
These are the typedefs in list.h :
typedef void* ListElement;
typedef ListElement(*CopyListElement)(ListElement);
typedef void(*FreeListElement)(ListElement);
These are the typedefs in user.h and MtmFlix.h :
typedef struct User_t *User;
typedef struct mtmFlix_t* MtmFlix;
I would like to use the following function in mtmflixCreate, but I can't seem to figure out how to cast the UserCreate and UserFree to (*void) ?
List listCreate(CopyListElement copyElement, FreeListElement freeElement);
MtmFlix mtmFlixCreate()
{
MtmFlix newMtmFlix = malloc(sizeof(*newMtmFlix));
if (newMtmFlix == NULL) {
return NULL;
}
newMtmFlix->seriesList=listCreate(?????);
newMtmFlix->usersList=listCreate(?????);
}
The following functions appear in user.h :
User UserCreate(MtmFlix mtmFlix, const char* username,int age);
Void UserFree(User user);
You don't. You have to create functions that have the needed types. Something like this:
ListElement CopyUserListElement(ListElement elem) {
// (ListElement) is not necessary here, but included for completeness
return (ListElement)CopyUser((User_t*)elem);
}
void FreeUserListElement(ListElement elem) {
UserFree((User_t*)elem);
}

gcc complaints about braces in initialiser (nested structs)

In chasing down a very opaque bug, I have been trying to compile with no warnings or errors. This part of my code worked fine, but gcc complains about the braces--it says there are braces missing and extra braces. I usually initialise a bit more sloppily but here I'm being as pedantic as possible with braces for each logical level of inclusion. The only struct I really care about initialising is the last one, the Ccfg. I thought I'd build up to it gradually as it contains nested other structs, but apparently even the ones preceding it are mis-initialized according to gcc.
Here's the code:
#define max_nodes 24
struct Cseg
{
int begin;
int arc;
int end;
};
struct Node
{
struct Cseg exit[4];
};
struct Core
{
int num_circles;
int num_nodes;
struct Node node[max_nodes];
};
struct Ccfg
{
struct Core core;
int dummy1;
int dummy2;
};
int main(void)
{
struct Cseg A = {0,1,2};
struct Node B =
{
{0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1}
};
struct Node C =
{
{0,1,2}, {1,3,0}
};
struct Core D =
{4, 4,
{
{ {0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1} },
{ {1,3,0}, {2,1,0}, {3,-2,1}, {2,-1,0} },
{ {3,1,2}, {0,1,2}, {1,-3,0}, {2,-3,1} }
}
};
struct Ccfg E =
{
{2, 2,
{
{ {0,1,1}, {0,2,1} },
{ {1,2,0}, {1,1,0} }
}
}
};
return 0;
}
Some of the initialisations are incomplete; that is deliberate. My real ccfg struct has many more fields but I've simplified it for this post. If someone could let me know what I'm doing wrong I'd appreciate it a lot. Thanks!
EDIT: in my working code, the initialiser for struct Ccfg E omits the innermost braces, and works fine (but gcc still warns me about it). I added them into this test because they seemed logically appropriate, but they actually generate an error--which I don't understand.
You are missing braces in some places. Specifically, if you have an array of structs, the entire array needs to be brace-wrapped; you were just wrapping each struct entry. I just added braces as needed and it works fine now. http://ideone.com/fork/HqxB9R
#define max_nodes 24
struct Cseg
{
int begin;
int arc;
int end;
};
struct Node
{
struct Cseg ex[4];
};
struct Core
{
int num_circles;
int num_nodes;
struct Node node[max_nodes];
};
struct Ccfg
{
struct Core core;
int dummy1;
int dummy2;
};
int main(void)
{
struct Cseg A = {0,1,2};
struct Node B =
{
{ {0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1} }
};
struct Node C =
{
{ {0,1,2}, {1,3,0} }
};
struct Core D =
{4, 4,
{
{ { {0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1} } },
{ { {1,3,0}, {2,1,0}, {3,-2,1}, {2,-1,0} } },
{ { {3,1,2}, {0,1,2}, {1,-3,0}, {2,-3,1} } }
}
};
struct Ccfg E =
{
{2, 2,
{
{ { {0,1,1}, {0,2,1} } },
{ { {1,2,0}, {1,1,0} } }
}
}
};
return 0;
}

Nested structure with the same name in C

I have a exercice that I have to realise a structure to match this line in C
int main() {
t_foo foo;
foo.foo.foo = 0;
return (0);
}
I tried to create a nested structure, but I can't create with a same name. Have you an idea ?
struct a
{
int foo;
};
struct c
{
int d;
struct a foo;
};
int main(void)
{
struct c foo;
foo.foo.foo = 2;
printf("%d\n",foo.foo.foo);
return 0;
}
For example you can do that the following way
#include <stdio.h>
typedef struct foo
{
struct
{
int foo;
} foo;
} t_foo;
int main(void)
{
t_foo foo;
foo.foo.foo = 0;
printf( "%d\n", foo.foo.foo );
return 0;
}
Or
#include <stdio.h>
typedef struct
{
struct foo
{
int foo;
} foo;
} t_foo;
int main(void)
{
t_foo foo;
foo.foo.foo = 0;
printf( "%d\n", foo.foo.foo );
return 0;
}

Resources