Use function pointer in struct - C compiler - c

I found an answer how to make function pointer in struct but I am still curious about
its operation. Can anybody explain this clearly?
Here is my question,
This code runs properly but...
char func_1(void);
char func_2(char);
struct mStruct
{
char name[100];
int age;
char (*func_1)(void);
void (*func_2)(char);
};
void init_struct(struct mStruct *pStruct)<-why this void function is necessary?
{
if(pStruct == NULL) {
pStruct = malloc(sizeof(struct mStruct));
}
(*pStruct).age = 25;
(*pStruct).func1 = &func1;
(*pStruct).func2 = &func2;
}
char func_1(void)
{
... ;
}
char func_2(char)
{
... ;
}
I already tried to eliminate the init_struct function, but all tries failed. My gcc compiler only accepts it as above. Does anybody know another way to initialize the struct without using a function
or why it is only acceptable as a void function?

Actually, besides the title, your question seems to have nothing to do with function pointers.
You have a struct mStruct with some members. For your question, it does not really matter what these members are.
With this struct, you don't need an initialization function. You can always simply use the struct and initialize it:
struct mStruct s;
s.member = 20;
But, this comes with a cost: You repeat yourself and when you want to change the struct (say, add another member), you will have to change lot of places. That's bad and can be fixed with an initialization function:
void init_struct(struct mStruct *pStruct)
{
pStruct->member = 20;
}
struct mStruct s;
init_struct(&s);
Now, you should not add other responsibilities to init_struct than to initialize it. In your example, you also allocate memory for the struct, in a buggy way. Instead, use another function for that:
struct mStruct* create_struct()
{
struct mStruct *pStruct = (struct mStruct*) malloc(sizeof(struct mStruct));
init_struct(pStruct);
return pStruct;
}
struct mStruct *pStruct = create_struct();
do_something_with(pStruct);
free(pStruct); // Don't forget this!
If you need more cleanup than just freeing the memory, write yet another function for it:
void destroy_struct(struct mStruct *pStruct)
{
cleanup(pStruct);
free(pStruct);
}
struct mStruct *pStruct = create_struct();
do_something_with(pStruct);
destroy_struct(pStruct); // Don't forget this!

Related

How to write after the end of the already initialized struct?

I have a struct initialized on a stack, and i want to write data in memory right after the struct and make a pointer inside a struct point to that data.
I know it is achievable on the stack/heap with uninitialized structure using malloc(sizeof(struct) + additional size) or alloca(). but can i perform initialization of a data after the struct is already initialized on the stack? and can i perform this initialization inside a initializator function?
Simple example:
struct TEST {
wchar_t* itest;
};
void init_struct(struct TEST* test) {
// point to the end of the struct
char* walk_ptr = (char*)test + sizeof(test);
test->itest = (wchar_t*)walk_ptr;
// initialize data after the struct
...
}
int main(void) {
struct TEST test;
init_struct(&test);
return 0;
}
You could do this by embedding the structure inside another structure to reserve memory for the extra data:
int main(void)
{
struct { struct TEST test; wchar_t data[NumberOfElements]; } S;
init_struct(&S.test);
…
}
However, the code in init_struct adds an incorrect size, sizeof(test), to the pointer. You likely wanted to add sizeof (struct Test), or, equivalently, sizeof *test, since you want to get past the struct TEST that test points to, not past a struct TEST * that test is.
However, even adding the correct size of the structure would not guarantee strictly conforming C code, since C implementations may insert padding between structure members. Properly we would add the offset of the data member. To do that, we nwould eed to give the structure a tag and then either make the structure definition visible to init_struct or pass the offset to init_struct. However, it is easier just to pass the address of the extra data:
void init_struct(struct TEST *test, wchar_t *data)
{
test->itest = data;
}
int main(void)
{
struct { struct TEST test; wchar_t data[NumberOfElements]; } S;
init_struct(&S.test, S.data);
…
}
Of course, a pointer can point anywhere, and there is no apparent reason the data should be immediate after the structure, so we can disconnect them:
int main(void)
{
struct TEST test;
wchar_t data[NumberOfElements];
init_struct(&test, data);
…
}

C function pointer and struct

I am new to C function pointer and structure. Here is what I want to achieve say there is a structure
typedef struct gfcrequest_t gfcrequest_t;
Later on this struct will be used to point to a function and the function will be called
gfcrequest_t *gfc_create();
gfr = gfc_create();
gfc_set_server(&gfr, server);
gfc_set_port(&gfr, port);
So are the following codes correct to initiate and later on I could add elements like server name and port number?
gfcrequest_t *gfc_create() {
struct out {
struct hostent *server;
int portno;
};
return out;
}
void gfc_set_port(gfcrequest_t **gfr, unsigned short port) {
gfr.portno = port;
}
void gfc_set_server(gfcrequest_t **gfr, const char *server) {
gfr.server = gethostbyname(server);
}
thats not how you do pointers to function.
to declare a pointer to function you do this:
if your function is:
int ft_somefink (int a, int b);
the pointer should be:
struct s_structure;
typedef struct s_structure t_structure;
struct s_structure
{
int (*funct)(int, int);
};
the typedef is there to simplify syntax.
its just an alias to avoid having to type "struct" everytime you use the structure.
you initialize it like so:
int main ()
{
t_structure name;
name.funct = &ft_somefink;
}
And call it like so:
int main()
{
t_structure name;
int a;
int b;
a = 1;
b = 2;
name.funct = &ft_somefink;
...
name.funct(a, b);
}
or like so if you pass the structure as pointer, it should look like this:
the main:
int main ()
{
t_structure *name;
...
function_somthing_useful(&name);
}
and the function:
void function_something_useful(t_structure **name)
{
if (!(*name = malloc(sizeof(t_structure))))
{
fprintf(stderr, "malloc error, not enough memory or swap nvm\n")
return ;
}
name->funct = &ft_somefink;
}
And, obviously, you call it then by:
name->funct(a, b);
note that you can malloc in main, doesnt matter. the idea to pass just the pointer is to avoid having to copy the whole structure everytime you pass it to a function.
the difference between . and -> operator is a dereferencing, but that would be another subject.
also i think it is better to pass the function as a pointer, instead of the whole thing because that might imply copying all of the functions instructions. not 100% sure of that tho... or rather depends on the system.
on linux reads are suposed to be "atomic", which, in my experience includes what happens on the stack. couldnt speak about other systems tho...
definitely could use someone to fill in the blanks here...

C Strings in Structs

I want my struct to carry a string. I defined it like so:
typedef struct myStruct {
char* stringy
} myStruct
and a function
free(char *stringy){
//structObj is a struct object
structObj->stringy = stringy
}
Is this correct? I have a feeling that since it's a local variable, stringy will be lost, and the pointer will point to garbage.
Sorry, new with C.
It would be garbage if you were somehow using char** stringy, but structObj->stringy = stringy means "you know the thing that stringy points to? Now structObj->stringy points to that". Of course, it is still possible to unset the value which the pointer is pointing to, and at that point dereferencing will yield garbage.
Here's an example to make it clearer:
#include<stdio.h>
typedef struct mStruct {
char* stringy;
} myStruct;
myStruct * structObj;
void doSomething(char* stringy)
{
structObj->stringy = stringy;
}
int main(int argc, char* argv)
{
char* a = "abc\n";
structObj = malloc(sizeof(myStruct));
doSomething(a);
a = "qxr\n";
printf(structObj->stringy);
}// prints "abc\n"
If stringy is defined in callers of free function, as long as they keep the actual string in its place (where stringy points), no problem.
There is not any local variable declaration in your code.
You have to declare:
typedef struct myStruct {
char* stringy
} myStruct;
free(char *stringy){
myStruct *structObj;
structObj->stringy = stringy;
}
Pay attention to the semicolon that I've added to the end of the typedef declaration.
This was not not in your code.
The object structObj is a struct whose type is myStruct.
Now, your parameter stringy comes from another site, it is not lost.
But the struct structObj will have duration only inside your "free" function.
EDIT
I have fixed an error: the right declaration has to be "pointer to structObj", which is done in this way:
myStruct *structObj;
Observe that now myStruct is a non-initialized pointer, so the following assignment is legal:
structObj->stringy = stringy;
but will not work.
However I think this goes beyond the scope of the original question...
myStruct is type which you defined for your struct myStruct .that to you need to create an object before using.
you need to do like this:
typedef struct myStruct {
char *stringy;
} myStruct_t; //user defined data type
myStruct_t *obj;
// you need to allocate memory dynamically.
obj= (myStruct_t *) malloc(sizeof(myStruct_t));
usage:
scanf("%s",obj->stringy);
printf("%s",obj->stringy);
in function:
my_free(char *str) //str is local string
{
obj->stringy=str;
}
your can also try this code :
typedef struct myStruct {
char stringy[20]; //char *stringy
} myStruct_t; //user defined data type
myStruct_t obj; //object creation
usage:
scanf("%s",obj.stringy);
printf("%s",obj.stringy);
in function:
my_free(char *str) //str is local string
{
strcpy(obj.stringy,str);
}
You're correct that as soon as what it points to goes out of scope, it will point to garbage: this is a dangling pointer. You'll need to allocate some memory and perform a copy to fix this:
add_string(my_struct* s, const char* c)
{
size_t len = strlen(c);
s->file = malloc(len + 1);
strcpy(s->file, c);
}
Don't forget that you'll need to free it when you're done:
void destroy_struct(my_struct* s)
{
free(s->file);
free(s);
}

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!

C - How to manipulate typedef structure pointer?

typedef struct
{
int id;
char* first;
char* last;
}* person;
person* people;
Hi.
How can I use this above, all set globally, to fill people with different "person"s? I am having issues wrapping my head regarding the typedef struct pointer.
I am aware pointers are like arrays, but I'm having issues getting this all together...
I would like to keep the above code as is as well.
Edit 1: char first should be char* first.
Ugly as sin. You really should redefine person to not be a pointer. Also don't use anonymous structs.
#include <stdio.h>
typedef struct {
int id;
char* first;
char* last;
}* person;
person* people = (person[]){
(person)&(struct {int id;char* first;char* last;}){0,"me","foo"},
(person)&(struct {int id;char* first;char* last;}){0,"you","foo"},
NULL
};
int main(void) {
while(*people) {
printf("%s %s\n", (*people)->first, (*people)->last);
people++;
}
return 0;
}
Don't bother with typedefs for structs. It's much clearer if you use structs with tags and then do your thing:
struct PERSON {
int id;
char *first;
char *last;
};
struct PERSON *people; /* people is a pointer to a struct PERSON. */
/* Allocate array of 42 struct PERSONS. */
people = malloc (42 * sizeof *people);
/* Now use people[0] to people[41]. */
You could simply create an array of structures of type person using something like following:
people = malloc (num_person * sizeof(person));
for (i = 0; i < num_person; i++) {
people[i]->first = malloc (size * sizeof(char));
people[i]->last = malloc (size * sizeof(char));
}
Following this, you could fill up each people struct with different parameters.
Typedefs that hide the real type are a bad idea.
If you really want the double indirection, I guess something like:
people = malloc(sizeof(person));
*people = malloc(SOME_NUMBER * sizeof(**people));
Will allocate what you need. You'd get an individual person structure out like:
(*people)[INDEX]
When using a particular person structure, you'll need to allocate memory for the first and last strings as well:
(*people)[INDEX].first = malloc(STRING_SIZE);
(*people)[INDEX].last = malloc(STRING_SIZE);
But simply removing the crazy double indirection will really clean things up and make everything a lot easier to use and understand:
people = malloc(SOME_NUMBER * sizeof(person));
people[INDEX].first = malloc(STRING_SIZE);
people[INDEX].last = malloc(STRING_SIZE);

Resources