I want to understand what this code means actually, esp. the last part where the function is put into curly braces. Is the broadcast_open function somehow calling the function broadcast_recv? If yes, how?
static void broadcast_recv(struct broadcast_conn *c, const rimeaddr_t *from)
{
printf("broadcast message received from %d.%d: '%s'\n",
from->u8[0], from->u8[1], (char *)packetbuf_dataptr());
}
static const struct broadcast_callbacks broadcast_call = {broadcast_recv};
static struct broadcast_conn broadcast;
PROCESS_THREAD(example_broadcast_process, ev, data)
{
broadcast_open(&broadcast, 129, &broadcast_call);
...
}
void broadcast_open(struct broadcast_conn *c, uint16_t channel, const struct broadcast_callbacks *u)
{
abc_open(&c->c, channel, &broadcast);
c->u = u;
channel_set_attributes(channel, attributes);
}
It seems that broadcast_callbacks is a struct defined something like this:
struct broadcast_callbacks
{
void (*callback)(struct broadcast_conn *, const rimeaddr_t *from);
};
Then the line
static const struct broadcast_callbacks broadcast_call = {broadcast_recv};
creates a new struct object whose member points to the broadcast_recv function. This member can now be used to call the broadcast_recv (which is probably part of what broadcast_open does).
You have probably seen simple variables initialized, e.g.:
int x = 4;
When it's an aggregate, such as a structure, braces are used around the initializer so the compiler knows where the initializer ends. In this case, it would appear that a function pointer is the first member of the struct.
int f(void) { return 1; }
struct t {
int (*f)(void);
int a, b, c;
char *d, *e, *f;
} a_t_instance = {
f
};
Someone can now call f() with (*a_t_instance.f)(), or even a_t_instance.f()
So yes, broadcast_open or something that it calls is probably calling broadcast_receive, using the pointer in the structure.
Related
Am I allowed to use a variable being initialized inside a designated initializer?
Consider the following listing:
struct A {
int a;
int * const a_ptr;
};
struct A foo(int a) {
struct A result = {
.a = a,
.a_ptr = &result.a
};
return result;
}
demo
Am I allowed to use result in this designated initializer expression? Is this behavior defined? Is this code portable?
Update
My bad, the example contains a potential stack corruption. The listing should be:
struct A {
int a;
int * const a_ptr;
};
void foo(int a) {
struct A result = {
.a = a,
.a_ptr = &result.a
};
bar(&result);
}
The initialization by itself is fine.
At the time result is declared, its address (as well as the addresses of its fields) is constant. So it is safe to use &result.a in the initializer of result.
What is a problem however is that you're returning a copy of this structure. This copy contains the address of a local variable that no longer exists, so attempting to use the value of the a_ptr member of the returned struct will trigger undefined behavior.
The question has changed completely, here is my new answer:
Your code is fine, you can check this, it won't assert on any platform.
You pass the pointer to the local variable result to bar. In bar that local variable still exists p points to that variable (result). Therefore the a_ptr still points to result.a.
But I'm just wondering what you're trying to achieve here.
#include <assert.h>
struct A {
int a;
int* const a_ptr;
};
void bar(struct A *p)
{
assert(p->a_ptr == &p->a);
}
void foo(int a) {
struct A result = {
.a = a,
.a_ptr = &result.a
};
bar(&result);
}
int main()
{
foo(2);
}
BTW:
struct A result = {
.a = a,
.a_ptr = &result.a
};
is equivalent to this:
struct A result;
result.a = a;
result.a_ptr = &result.a;
but for latter you'd need to declare int* a_ptr; instead of int* const a_ptr;.
I'm using a library that callbacks to my functions. Those functions do basically the same thing; the only difference is that they have a different type of structure passed to the function.
static void func_a(void * a, TypeA * b) {
...
printf("%d\n", b -> code);
}
static void func_b(void * a, TypeB * b) {
...
printf("%s\n", b -> string);
}
Is there a way in C to avoid using duplicate code in this case?
You could write a single function like this:
enum struct_type {
A, B, // ...
};
static void func(void *a, void *b, enum struct_type st)
{
// ...
char const *str;
switch(st) {
case A:
str = ((TypeA *)b)->string;
case B:
str = ((TypeB *)b)->string;
// ...
}
printf("%s\n", str);
}
Is that what you are looking for?
One simple way is to
Make use of an extra parameter type which tells you what type of struct you want to use
use void* to store your required struct data.
A simple prototype would be like this:
static void func_common( void *a, void* data , int type )
{
/* data contains your required data structure */
/* type tells what type you want to use */
}
Inside func_common use can operate on your required data based on type
if (type == STRCUT1)
printf("%d\n", *(int *)data->code);
else if (type == STRCUT2)
printf("%s\n", (char*) data->string);
Note: You will have to take care of converting void* to required types based on what you are passing.
I upvoted Peter's answer, but wanted to point out the possibility of using struct "inheritance" (also see here) as an alternative solution.
The reason I would suggest this approach is that it provides better type safety during compile time, as we avoid using the void * pointer and the compiler can check for type errors.
i.e.,:
typedef struct {
int type_id;
int i;
float f;
} common_s;
typedef struct {
common_s parent;
int code;
} type_A_s;
typedef struct {
common_s parent;
char *string;
} type_B_s;
static void func_common(void *a, common_s *b) { /* ... */ }
static void func_a(void *a, type_A_s *b) {
func_common(a, &b->parent);
printf("%d\n", b->code);
}
static void func_b(void *a, type_B_s *b) {
func_common(a, &b->parent);
printf("%s\n", b->string);
}
This is similar to how the kernel handles network socket addresses, where IP4, IP6 and Unix socket address types all have a common header field (which includes the address type identifier), and some functions are common to all types while others use the type identifier to route the address object to the correct function.
I have a function func1 with the signature
int func1(struct a *a1, int b1, const enum c c1);
I want to call this function using another predefined function with the signature
void callerfunc(void (*func)(void *params), void *params);
Note that I cannot modify the above two functions.
To do so, I considered making a new struct pointed to by params which can then be used with a wrapper function to call func1, i.e.
struct param_holder {
struct a a1;
int b1;
enum c c1;
};
int wrapper_func1(void* params) { // params points to initialized struct
return func1(params->a1, params->b1, params->c1);
}
I would like to know if there is a different or better way of achieving this, possibly without creating the wrapper function. Thanks!
Using wrapper is a good solution to me. Just cast before using void pointer :
int wrapper_func1(void* void_params) { // params points to initialized struct
struct param_holder *params = (struct param_holder *) void_params;
return func1(params->a1, params->b1, params->c1);
}
We have a lot of duplicate code that looks like this:
void WriteA(A *to, A *from);
void WriteB(B *to, B *from);
void WriteC(C *to, C *from);
void WriteA(A *to, A *from){
*to = *from;
}
void WriteB(B *to, B *from){
*to = *from;
}
void WriteC(C *to, C *from){
*to = *from;
}
Even though C doesn't have function overloading or templates, I'd like to make this a single generic function. I suppose my only option here, is to use void pointers.
void Write(void *to, void *from);
However, there doesn't seem to be a way to derive the type once inside the function:
void Write(void *to, void *from){
*to = *from
}
compiler error: illegal type(s): void '=' void
There also doesn't seem to be a way to pass a third parameter which is a typename(again, something I assume only C++ can do with templates).
How would I go about writing this kind of function? I'd like to avoid the pre-processor if possible.
I thought I could maybe do this:
void Write(void *to, void *from){
memcpy(pTo, pFrom, sizeof(*pTo));
}
but,
compiler error: don't know size of object
One approach would be to use the C Preprocessor if you have a dependency on the struct members.
However based on your comment you really have only a single dependency on the struct type and members which is the assignment which is done in a particular place.
The easiest thing would be to use the suggestion from Leonardo Herrera in the comment above and pass in the struct size and then use memcpy() with the size of the struct argument.
Another possibility is to create two functions, one which does the work before the assignment and a second which does the work after the assignment and then call the first function, do the actual assignment, and then call the second function. For instance:
// define the structs that we are using.
typedef struct {
int jj;
int kk;
} s1;
typedef struct {
int kk;
int ii;
int jj;
} s2;
// define the function that does the first part of the work
void PhaseOne (/* arg list */)
{
// phase one of the functionality
}
// define the function that does the second part of the work
void PhaseTwo (/* arg list */)
{
// phase two of the functionality
}
myFunctionUser (void)
{
s1 a1, b1;
s2 a2, b2;
// do things with a1 and b1 in prep to call the function
// do things with a2 and b2 in prep to call the function
PhaseOne (/* arg list */);
a1 = b1;
PhaseTwo (/* arg list */);
PhaseOne (/* arg list */);
a2 = b2;
PhaseTwo (/* arg list */);
// do more stuff
}
If there is need for state to be communicated between PhaseOne() and PhaseTwo() or if there is some change needed to the variables which are being assigned based on the state from PhaseOne() or PhaseTwo() then you might need to have a struct or other variable type for that.
However another thing would be to write a function that takes a pointer to another function and in the other function do the assignment. This is borrowing the idea of how the C Standard Library uses a comparison function with the qsort() function. And using this approach if there are additional things to do with the structs besides the assignment then the function pointed to would be the place to do it since at that point you can do a cast to the appropriate type and then do whatever.
// define the structs that we are using.
typedef struct {
int jj;
int kk;
} s1;
typedef struct {
int kk;
int ii;
int jj;
} s2;
void AssignS1 (void *a, void *b) { *((s1 *)a) = *((s1 *)b); return; }
void AssignS2 (void *a, void *b) { *((s2 *)a) = *((s2 *)b); return; }
void myFunction (void *a, void *b, void (*pFunc)(void *x, void *y))
{
// do stuff
pFunc(a, b); // do the assignment
// do more and more and tons of stuff
}
myFunctionUser (void)
{
s1 a1, b1;
s2 a2, b2;
// do things with a1 and b1 in prep to call the function
// do things with a2 and b2 in prep to call the function
myFunction (&a1, &b1, AssignS1);
myFunction (&a2, &b2, AssignS2);
// do more stuff
}
Just for grins here is an approach using the C Preprocessor to generate source based on a particular struct type. It is quite ugly and difficult for debugging and requires some degree of discipline on the part of the programmer. This is a small and simple function to illustrate the procedure and I guarantee you that it will not scale well.
// define a macro that will generate various type specific versions of a function.
#define WriteThing(s) void WriteThing##s (s *a, s *b) \
{ *a = *b; if (a->jj != 4) { a->jj += b->jj + 10;} return; }
// define the function we will use to call the above function based on the type of the arguments
#define WriteThingCall(s,a,b) WriteThing##s (a, b)
// define the structs that we are using.
typedef struct {
int jj;
int kk;
} s1;
typedef struct {
int kk;
int ii;
int jj;
} s2;
// generate the functions we are going to need for our different types
WriteThing(s1)
WriteThing(s2)
// example function of how to use this approach.
void func (void)
{
s1 a1 = {0}, b1 = {0};
s2 a2 = {0}, b2 = {0};
WriteThingCall(s1, &a1, &b1);
WriteThingCall(s2, &a2, &b2);
}
Given that you are trying to duplicate what can be achieved in C++, why not duplicate what C++ does and implement inheritance and virtual functions?
This is whiteboard code, neither compiled nor tested, but is very similar to things I've done in the past when implementing OO designs in C. Take it as a pattern you can use and expand.
Sticking to your example code, where you want a generic copy function, first define the abstract base class.
typedef struct base_class
{
void (*copy) (const void *this, void *to);
}
Now some inherited classes:
typedef struct A
{
const base_class *base;
// Other members
} A;
typedef struct B
{
const base_class *base;
// Other members
} B;
Create the underlying copy functions, and constructors for the derived classes. The assert tries to provide some type safety
void copy_A(const void *this, void *to)
{
assert(((const A *)this)->base == ((A *)to)->base)
memcpy(to, this, sizeof(A));
}
void make_A(A *newA)
{
const base_class base = {copy_A};
assert(newA);
newA->base = &base;
// other initialization
}
void copy_B(const void *this, void *to)
{
assert(((const B *)this)->base == ((B *)to)->base)
memcpy(to, this, sizeof(B));
}
void make_B(B *newB)
{
const base_class base = {copy_B};
assert(newB);
newB->base = &base;
// other initialization
}
Finally, your generic copy method:
void Write (void *to, const void *from)
{
const base_class *source_vtable = from;
source_vtable->copy(from, to);
}
This is not typesafe, in that there is no guarantee *from contains a vtable. To make it bullet proof, you really want your base_classto contain an initial tag field which can be checked to ensure there really is a function table there.
The base_class can be expanded to contain multiple common functions.
struct MyStruct
{
int i;
double arr[10];
};
struct MyStruct func()
{
};
When returned from the function, will be fully copied to a local variable?
struct Mystruct ms = func();
Yes you can, the structure will be fully copied.
Yes, if func() returns a variable of type Mystruct.
The correct way to do this:
void func(struct MyStruct* by_ref);
int main()
{
struct MyStruct ms;
func(&ms);
}
This won't upload a bombastic struct on the stack, nor will you get issues with static variables. Returning a pointer to a static variable is very bad for the following reasons:
It breaks private encaptulation. Very bad program design.
A multi-threaded program doing this gets vulnerable.
Pure bugs, as in this example:
static uint8 static_str[6];
uint8* func(const uint8 str[6])
{
uint8 i;
for(i=0; i<6; i++)
{
static_str[i] = str[i];
}
return static_str;
}
int main()
{
print_strings(func(“hello”), func(“world”));
}
The output from a function printing the two strings will be either “hello hello” or “world world” (depending on the order of evaluation of function parameters).
You have no return value so in any case you need to set that. Furthermore, it is better to use a pointer:
struct MyStruct* func()
{
struct MyStruct *pMyStruct=calloc(1,sizeof(struct MyStruct));
/* fill struct */
return pMyStruct;
};