Defining a function as a function pointer

Mainly for fun, I decided to write my own minimal test environment for my C code. I use the base one struct

for the test information, create an array of tests struct

, and then iterate over them to run all the tests. This amounts to very little work for a fairly elegant solution (imho).

However, one thing that is a little annoying is that I cannot figure out how to define functions as function pointers instead of defining a function and then create a function pointer later.

I have the following (which works great):

typedef int (* test_p) (void);

struct test {
    char * desc;
    test_p func;
};

int
example_test (void) {
    puts("This is a test");
    return 0;
}

void
run_test (char * test_name, test_p test) {
    printf("Testing %s\t\t\t[ PEND ]\r", test_name);
    char * test_result = (test() ? "FAIL" : "PASS");
    printf("Testing %s\t\t\t[ %s ]\n", test_name, test_result);
}

int
main (void) {
    struct test test_list [] = {
        { "example test", (test_p )example_test }
    };

    for ( int i = 0; i < 1; i ++ ) {
        run_test(test_list[i].desc, test_list[i].func);
    }

    return 0;
}

      

However, I hope I can remove the need for casting in struct

and instead define the function as a function pointer from the start. Below is an example of how I would like this to work (assuming many of the same things as above):

test_p
example_test = {
    puts("This is a test");
    return 0;
}

      

If I could do something like this, then in struct

I could just have a field func

example_test

instead of (test_p )example_test

. Is this possible (or something like that)? If not, is there a reason why not (if that reason is just "because it was not added to the language", that's fine)?

+3


source to share


2 answers


A function pointer is one kind of thing and a function is a different kind, so you cannot force the latter to be the first. But if you use a function name where a function pointer is expected, this creates a function pointer, so you can just remove the unnecessary cast as WhozCraig said in the first comment above. You write

If I could do something like this, then in the structure I could just have the field func example_test and not (test_p) example_test.

You can do this with example_test, defined in the same way as in your current code ... have you tried this?

You can also forward the function declaration, for example:

typedef int test_func(void); // note no indirection
typedef test_func* test_p;

test_func example_test;

      

It would be nice if you could use this syntax when you define a function like in your syntax, but there is simply no way to do it in C ... you have to explicitly specify the type and return parameter of the list.



One more detail: when you call a function pointed to by a function pointer, you don't have to look for it ... that's why you were able to write

test()

      

instead

(*test)()

      

although the latter also works. (Actually, because reverence is devoid, (********test)()

also works ... but only do this if you are trying to win an obfuscation contest.)

+3


source


What you are describing is a kind of meta-programming. Instead of writing code to explicitly solve the problem, you are dealing with some kind of syntactic structure that will allow you to define a whole raft of test functions without unnecessary jerking.

In Lisp, you will use macros. In C ++, you can use templates and / or lambdas. In C, you use macros.

So, you need to write a macro that:

  • takes a name and descriptive text as arguments
  • defines a static variable of a function of type (created with that name using label insertion)
  • defines a function (using the name generated by the token insert)


[edit] At this point, you have achieved your goal: you created a function and gave it a name that is (only) a pointer to the function, and you can use that name in your structure without casting. I would suggest one more step, a macro:

  • adds variable / function and descriptive text to the list of checked functions.

Your template loop then iterates over the structure calling each function and reports the results using descriptive text. The problem has been resolved.

Some people don't like macros, but they are perfect for this situation and there is no other way to do it in C. I did something similar before switching to C ++.

+1


source







All Articles