Where is this pointer actually pointing? - c

I'm trying to learn c using learncodethehardway c book. In ex19 I have the following code:
int Monster_init(void *self)
{
Monster *monster = self;
monster->hit_points = 10;
return 1;
}
int Monster_attack(void *self, int damage)
{
Monster *monster = self;
printf("You attack %s!\n", monster->proto.description);
monster->hit_points -= damage;
if(monster->hit_points > 0) {
printf("It is still alive.\n");
return 0;
} else {
printf("It is dead.\n");
return 1;
}
}
Object MonsterProto = {
.init = Monster_init,
.attack = Monster_attack
};
This is the Object structure:
typedef struct {
char *description;
int (*init)(void *self);
void (*describe)(void *self);
void (*destroy)(void *self);
void *(*move)(void *self, Direction direction);
int (*attack)(void *self, int damage);
} Object;
And this is the Monster structure:
struct Monster {
Object proto;
int hit_points;
};
I'm having a tough time wrapping my head around the Monster_init and Monster_attack functions. I have a MonsterProto variable of type Object defined and inside there .init is set to the Monster_initfunction and .attack is set to the Monster_attack function.
I think I understand the notion of void in terms of declaring a function that has side effects but doesn't need to return something. What I don't understand is what exactly is the void *self pointer pointing at and why does it allow me to call a function with no arguments? What is the purpose of the self pointer?
I didn't want to include too much code here but if this is not enough context to answer the question, then you can find all the code here.
I appreciate any pointers in the right direction; nu pun intended :)

This code seems to be effectively implementing a kind of object-oriented approach.
self is the address of the struct Monster that you pass to those functions. Each of those functions operates on an individual object, and passing in the pointer to that object is how they know which one to work on.
This:
.init = Monster_init,
is not "calling a function with no arguments" - the init member of your struct is a pointer to a function returning an int and accepting a single void * parameter, and that line assigns the address of Monster_init() to it. This way, if you have a pointer to an object, you can call int n = myobject->proto.init(&myobject); or similar without knowing which actual function gets called. With a different object, you might be calling a different function with the same line of code.

Related

C - How to pass _self into a function thats assigned to a pointer

I'm probably getting mixed up as I'm a OO developer. I'm trying to have several instances that call a common method.
I want to somehow reference the caller in a function that is assigned thus...
header
typedef struct _Part Part;
struct _Part {
void (*move)();
}
code
void move(Part p) {
}
void main() {
Part part1;
part1.move = move(part1); <-- Won't compile
part1.move();
}
Is there some way of making this work or do I have to stop thinking like an OO dev and just call the move method directly, passing in the instance?
Declare the structure like
typedef struct _Part Part;
struct _Part {
void (*move)( Part);
};
and just write
part1.move = move;
The function designator is implicitly converted to a pointer to the function.
And then write
part1.move( part1 );

Create a test function for multiple typedefs - C

I usually like to have a bit more of a head start before I ask a question but I am a bit stuck on how to even start this.
I am tasked with creating a small testing framework in C to use strictly with A LOT of different typedef structs.
Say I have a function that returns mytype_t:
typedef struct mytype {
void * data;
} mytype_t;
mytype_t my_type_func(char *p) {
mytype_t q;
q->data = p;
return q;
}
Now I want to write a function to make sure everything is working as it should:
void CUSTOM_ASSERT(void (*test_func)(char*), mytype_t r){
mytype_t p = (*test_func);
if(p->data == r->data){
puts("Test X Passed");
}
Called from driver.c:
int main(void) {
mytype_t t;
t->data = "test";
char *test = "test";
CUSTOM_ASSERT(my_type_func(test), t);
}
Now this works all well and good for this one type and function but there are over 100 typedef structs and functions that take none to 10 parameters plus some parameters can be other typedefs. That makes using a va_list a little tricky as there are no variadic macros for these types (that I know of).
What is the best way to approach this? I was trying something like:
void CUSTOM_ASSERT(void (*test_func)(...), void *should)
But I have no clue as to what return type the function pointer is supposed to be able to cast the 2nd parameter of CUSTOM_ASSERT.

How to pass structure to callback function as an argument

I am learning C and trying to pass structure to call back function. Gone through online resources but unable to pass structure to call back function. Here is my code.
// myvariables.h
struct callbackStruct
{
int a;
int b;
int c;
};
extern struct callbackStruct callbackStructObject;
typedef void (*callback)(struct callbackStruct);
extern void callback_reg(callback pointerRefCallback);
// Operations.c
struct callbackStruct callbackStructObject;
void callback_reg(callback pointerRefCallback) {
(*pointerRefCallback)(callbackStructObject);
}
// main.c
struct callbackStruct myCallbackStruct1;
void my_callback(struct callbackStruct myCallbackStruct) {
printf("A value:%d" + myCallbackStruct.a);
}
int main()
{
callback ptr_my_callback = my_callback(myCallbackStruct1);
callback_reg(ptr_my_callback);
return 0;
}
Can anyone resolve this scenario?
The type callback is a function pointer type, e.g. a variable of that type is a pointer that points to a function that accepts a struct callbackStruct as single parameter:
typedef void (*callback)(struct callbackStruct);
So when you write (in main):
// ...
callback ptr_my_callback = // HERE
// ...
The expression at HERE must be the address of a function with the correct signature. You write:
my_callback(myCallbackStruct1);
Since my_callback is a function that returns nothing (void) and the above expression calls this function, the expression
callback ptr_my_callback = my_callback(yCallbackStruct1);
is not well formed (syntactically, as well as from the perspective of the type system).
Assuming that my_callback is the function that you want to work as a callback, you need to store its address in the pointer ptr_my_callback:
callback ptr_my_callback = &my_callback;
It's kind of unclear what your code is supposed to achieve, though, so I cannot really help you any further.

Pointer at function: access the data inside a structure?

I listed some example code below and the question is if there is a way for the function_name to access the value of number from struct_name?
typedef struct struct_name {
int number
void (*func)();
} * struct_name_ptr;
void function_name() {
//access number from struct
}
main() {
struct_name_ptr newobject;
newobject->func=&function_name;
newobject->func(); //can it print the value of the number in the structure above?
}
Uh - no.
A struct can certainly contain a function pointer. But the function you call wouldn't have any knowledge of the struct. Unless you passed a pointer as a function argument, or made the struct global.
With my limited knowledge of programming, I don't think this is possible. Though the struct contains a function pointer, the address of the function assigned to it is different and I don't think there will be anyway for it to access it unless you pass it as an argument.
Well, two things, struct_name->number should have a value, and it either needs to be in the same scope as &function_name or it needs to be explicitly passed. Two ways to do it:
/* Here is with a global calling struct */
#include<stdio.h>
typedef struct struct_name {
int number;
void (*func)();
} * struct_name_ptr;
struct struct_name newobject = { 0 };
void function_name() {
printf("%d",struct_name);
}
void main() {
struct struct_name_ptr newobject;
newobject->func=&function_name;
newobject->func();
}
/* And one with a modified function_name */
#include<stdio.h>
typedef struct struct_name {
int number;
void (*func)();
} * struct_name_ptr;
void function_name(struct_name) {
printf("%d",struct_name);
}
void main() {
struct struct_name_ptr newobject;
newobject.number = 0;
newobject->func=&function_name;
newobject->func(newobject);
}
No, a pizza won't ever know what the pizza delivery guy, who delivered it, looks like.
A regular function is just an address in memory. It can be called using a function pointer like in this case. In any case: The function won't know how it was called. In particular it won't know that it was called using a function pointer that's part of (a piece of memory corresponding to) some struct.
When using a language with classes like C++, member functions will have a hidden argument which is a pointer to the class instance. That's how member functions know about their data.
You can 'simulate' a simple OOP in plain C, for your example like:
typedef struct {
int number;
void (*func)();
} class;
void function_name(class *this) {
printf("%d",this->number);
}
#define CALL(c,f) c.f(&c)
int main() {
class object={12345,function_name};
CALL(object,func); // voilá
}

Passing struct to function

I'm a new C programmer and I wanted to know how I can pass a struct through to a function. I'm getting an error and can't figure out the correct syntax to do it. Here is the code for it....
Struct:
struct student{
char firstname[30];
char surname[30];
};
struct student person;
Call:
addStudent(person);
Prototype:
void addStudent(struct student);
and the actual function:
void addStudent(person)
{
return;
}
Compiler errors:
line 21: warning: dubious tag declaration: struct student
line 223: argument #1 is incompatible with prototype:
This is how to pass the struct by reference. This means that your function can access the struct outside of the function and modify its values. You do this by passing a pointer to the structure to the function.
#include <stdio.h>
/* card structure definition */
struct card
{
int face; // define pointer face
}; // end structure card
typedef struct card Card ;
/* prototype */
void passByReference(Card *c) ;
int main(void)
{
Card c ;
c.face = 1 ;
Card *cptr = &c ; // pointer to Card c
printf("The value of c before function passing = %d\n", c.face);
printf("The value of cptr before function = %d\n",cptr->face);
passByReference(cptr);
printf("The value of c after function passing = %d\n", c.face);
return 0 ; // successfully ran program
}
void passByReference(Card *c)
{
c->face = 4;
}
This is how you pass the struct by value so that your function receives a copy of the struct and cannot access the exterior structure to modify it. By exterior I mean outside the function.
#include <stdio.h>
/* global card structure definition */
struct card
{
int face ; // define pointer face
};// end structure card
typedef struct card Card ;
/* function prototypes */
void passByValue(Card c);
int main(void)
{
Card c ;
c.face = 1;
printf("c.face before passByValue() = %d\n", c.face);
passByValue(c);
printf("c.face after passByValue() = %d\n",c.face);
printf("As you can see the value of c did not change\n");
printf("\nand the Card c inside the function has been destroyed"
"\n(no longer in memory)");
}
void passByValue(Card c)
{
c.face = 5;
}
The line function implementation should be:
void addStudent(struct student person) {
}
person is not a type but a variable, you cannot use it as the type of a function parameter.
Also, make sure your struct is defined before the prototype of the function addStudent as the prototype uses it.
When passing a struct to another function, it would usually be better to do as Donnell suggested above and pass it by reference instead.
A very good reason for this is that it makes things easier if you want to make changes that will be reflected when you return to the function that created the instance of it.
Here is an example of the simplest way to do this:
#include <stdio.h>
typedef struct student {
int age;
} student;
void addStudent(student *s) {
/* Here we can use the arrow operator (->) to dereference
the pointer and access any of it's members: */
s->age = 10;
}
int main(void) {
student aStudent = {0}; /* create an instance of the student struct */
addStudent(&aStudent); /* pass a pointer to the instance */
printf("%d", aStudent.age);
return 0;
}
In this example, the argument for the addStudent() function is a pointer to an instance of a student struct - student *s. In main(), we create an instance of the student struct and then pass a reference to it to our addStudent() function using the reference operator (&).
In the addStudent() function we can make use of the arrow operator (->) to dereference the pointer, and access any of it's members (functionally equivalent to: (*s).age).
Any changes that we make in the addStudent() function will be reflected when we return to main(), because the pointer gave us a reference to where in the memory the instance of the student struct is being stored. This is illustrated by the printf(), which will output "10" in this example.
Had you not passed a reference, you would actually be working with a copy of the struct you passed in to the function, meaning that any changes would not be reflected when you return to main - unless you implemented a way of passing the new version of the struct back to main or something along those lines!
Although pointers may seem off-putting at first, once you get your head around how they work and why they are so handy they become second nature, and you wonder how you ever coped without them!
You need to specify a type on person:
void addStudent(struct student person) {
...
}
Also, you can typedef your struct to avoid having to type struct every time you use it:
typedef struct student{
...
} student_t;
void addStudent(student_t person) {
...
}
Instead of:
void addStudent(person)
{
return;
}
try this:
void addStudent(student person)
{
return;
}
Since you have already declared a structure called 'student' you don't necessarily have to specify so in the function implementation as in:
void addStudent(struct student person)
{
return;
}

Resources