C++/C Function Pointers That Return Void*

how to use void pointer as function return type In C

You can write a perfectly fine generic function this way, but:

    result = array[rand()%(length-1)];

This is dereferencing the void pointer array while also attempting to store it into a pointer result. What you want to store is the address at that offset:

    result = array + rand()%(length-1);

However, you can't perform arithmetic like this on void pointers either, as the size of the underlying type is not known (some compilers allow sizeof(void)==1 as an extension). With a non-void array, the number of bytes a given element consumes, and thus the number of bytes to increment by when doing arithmetic on the address, is encoded in the type. In a generic function operating on void pointers like this one you'll need to explicitly pass the size of the type.

void *randomNum(void * array, size_t size, size_t length)

Now perform the calculation by casting array to a char pointer, which forces arithmetic on array to occur in increments of 1 byte times the provided size parameter:

    result = (char*)array + (rand()%(length-1)) * size;
^ ^

You can then call randomNum with randomNum(array, sizeof(*array), 9)

However, you still need to cast the return value of the function before dereferencing it.

    printf("%d\n", *(int*)randomNum(array,sizeof(*array),9));

C++/C function pointers that return void*

You are doing one thing incorrectly - you are trying to invoke your 'ptr' function before invoking 'function'. What you were supposed to do is to pass just a pointer to 'ptr' and invoke 'ptr' using passed pointer from 'function' like that:

void ptr(int x)
{
printf("from ptr [%d]\n", x);
}

int function(int a, int b , void (*func)(int) )
{
printf( "from function a=[%d] b=[%d]\n", a, b );
func(a); // you must invoke function here

return 123;
}

void main()
{
function( 10, 2, &ptr );
// or
function( 20, 2, ptr );
}

which gives:

from function a=[10] b=[2]
from ptr [10]
from function a=[20] b=[2]
from ptr [20]

which is what you wanted

for

function(20, 20, ptr(20));

to work - you would have to have sth like:

// 'ptr' must return sth (int for example)
// if you want its ret val to be passed as arg to 'function'
// this way you do not have to invoke 'ptr' from within 'function'
int ptr(int);
int function(int, int , int);

Function Pointer with void* return and void* parameters

void * is a pointer type. You're not passing pointers, you're passing values, so that's not going to compile. It accidentally "works" for int because pointers themselves are represented as integers by most C compilers.

If you pass pointers to int, float, and double instead of the int, float, and double themselves, you will avoid that compiler error. You'd also need to change int_add and friends to take pointers, and you'd have to make sure you dereferenced the pointers before using them. You'll also have to return pointers, which means you'll have to malloc some memory on the heap, because the stack memory assigned to your local variables will be invalid once your function exits. You'll then have to free it all later... in the end, this is going to result in something considerably more complicated than the problem it appears you are trying to solve.

I have to ask why you are trying to do this? C is really not the best language for this type of pattern. I'd suggest just calling the int_add, float_add, etc. functions directly instead of trying to abstract them in this way.

What's the void* of function pointers?

What's the void* of function pointers?

In a way: All pointers to functions.

A special thing about pointer to void is that it can point to any object, and any object pointer can be converted to pointer to void and back, which yields the original pointer.

All pointers to functions can be converted to other pointers to function types and be converted back, yielding the original value.


In another way: There is no analogous pointer type for function pointers in the sense that there is no such pointer type into which all function pointer types would implicitly convert to in same manner as object pointers implicitly convert to void*.


How can I fix this?

Convert the pointer explicitly if you need to, using a cast. Use reinterpret_cast in C++.

P.S. Conversion to void* is not guaranteed to work on all systems and is therefore not universally portable. It is "conditionally supported" according to C++ standard. It is guaranteed to work in POSIX conforming systems.

Is void *function() a pointer to function or a function returning a void*?

The function has the return type void *.

void *function();

So I always prefer in such cases to separate the symbol * from the function name like

void * function();

And as Jarod42 pointed to in a comment you can rewrite the function declaration in C++ using the trailing return type like

auto function() -> void *;

If you want to declare a pointer to function then you should write

void ( *function )();

where the return type is void Or

void * ( *function )();

where the return type void *.

Or a pointer to function that returns pointer to function

void * ( *( *function )() )();

Pointer to a function and its return type (void)

The declaration is read as follows:

        function        -- function is a 
*function -- pointer to
(*function) () -- function taking unspecified parameters
*(*function) () -- returning pointer to
void *(*function) (); -- void

So, function is a pointer to a function type, not a function itself. You could have multiple functions, each returning pointers to void:

void *foo( void )    { ... }
void *bar( void ) { ... }
void *bletch( void ) { ... }

You can use the function pointer to point to each of those functions, and decide at runtime which to call:

if ( condition1 )
function = foo;
else if ( condition2 )
function = bar;
else
function = bletch;

void *ptr = function(); // or (*function)();

Can a function pointer type that takes no arguments and returns void, be used with functions that do take arguments and return a value?

The C11 standard §6.3 Conversions, and more precisely §6.3.2.3 Pointers ¶8 says:

A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.

The GTK code places the onus on the programmer to pass the appropriate type of function pointer to the function taking a callback.

g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);

Where activate is a function that returns void but takes two parameters. (G_CALLBACK is a macro that simply casts to GCallback).

Let's assume the two parameters are int; their type is coincidental to the discussion.

extern void activate(int, int);

The code in g_signal_connect() gets 4 pointers. The third is the callback; it is formally of type void (*callback)(void).

The code inside g_signal_connect() expects to call the callback with 2 integers (arg1 and arg2), so it is required to use:

((void (*)(int, int)callback)(arg1, arg2);

to force the 'generic' type of the callback to the correct function pointer type — otherwise, it cannot avoid invoking undefined behaviour. You're required to know that g_signal_connect() requires such a pointer as the callback parameter, cast to the generic type, and you must pass it such a pointer suitably cast.

Remember, too, that one way of exhibiting 'undefined behaviour' is to 'behave as expected, even though the expectations are not guaranteed by the standard'. Other ways of exhibiting undefined behaviour include crashing or corrupting memory.


Side note.

C11 §6.2.5 Types ¶28 says:

A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.48) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.

48) The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.

The requirements of §6.3.2.3¶8 seem to imply that all pointers to different function types must have the same representation and alignment requirements as each other; otherwise, it becomes hard to guarantee the round-trip conversion requirement of §6.3.2.3¶8.

Another consequence of §6.2.5¶28 is that you cannot reliably convert between a pointer to function type and a pointer to object type such as void *. This has consequences for functions such as dlsym(); it is hard to use them cleanly — the compiler is likely to complain if you have stringent warning levels enabled.

Compiling some code which converts between function pointer and object pointer (and vice versa), GCC 9.3.0 with gcc -std=c99 -O3 -Wall -pedantic -Wdeclaration-after-statement -Wold-style-definition -Wold-style-declaration -Wnested-externs -Wmissing-prototypes -Werror … gives:

…: error: ISO C forbids conversion of function pointer to object pointer type [-Werror=pedantic]
…: error: ISO C forbids conversion of object pointer to function pointer type [-Werror=pedantic]

It's a warning if you don't have -Werror or -pedantic-errors in effect, and it's ignored if you don't have -pedantic or -pedantic-errors in effect.

Beware the differences between -pedantic (aka -Wpedantic) and -pedantic-errors, as documented by GCC under Options to Request or Suppress Warnings.

Casting A Function Pointers Return Type in C

The C11 standard §6.2.5 Types ¶28 says:

A pointer to void shall have the same representation and alignment requirements as a
pointer to a character type.48) Similarly, pointers to qualified or unqualified versions of
compatible types shall have the same representation and alignment requirements. All
pointers to structure types shall have the same representation and alignment requirements
as each other. All pointers to union types shall have the same representation and
alignment requirements as each other. Pointers to other types need not have the same
representation or alignment requirements.

That means, in particular, that pointers to functions do not have to have the same representation as any pointer to object type. There are, or at least were, machines where pointers to functions were bigger than pointers to objects (and I'm not referring to small, medium, compact, large, huge models and 80x86 chips — I believe IBM AS/400, later iSeries, had pointers to functions that were bigger than any pointer to object). Also, as Ajay Brahmakshatriya points out in a comment, some ABIs (application binary interfaces) can have different calling conventions for different function types, so converting a function pointer to the 'wrong' type and then invoking it via that converted pointer may end up wreaking havoc too. This particularly applies to pointers versus floating point versus other types. Usually (but it is by no means guaranteed), functions returning pointers will return the pointer the same way regardless of the type of the pointer returned.

And §6.3.2.3 Pointers ¶7-8 says:

A pointer to an object type may be converted to a pointer to a different object type. If the
resulting pointer is not correctly aligned68) for the referenced type, the behavior is
undefined. Otherwise, when converted back again, the result shall compare equal to the
original pointer. When a pointer to an object is converted to a pointer to a character type,
the result points to the lowest addressed byte of the object. Successive increments of the
result, up to the size of the object, yield pointers to the remaining bytes of the object.

A pointer to a function of one type may be converted to a pointer to a function of another
type and back again; the result shall compare equal to the original pointer. If a converted
pointer is used to call a function whose type is not compatible with the referenced type,
the behavior is undefined.

As you wrote the code, you'd be calling the function through the cast type, which would lead to undefined behaviour. It might work, but it might stop working and you'd have no recourse except to rewrite the code to avoid the undefined behaviour.

This means that you are not supposed to write your front-end function pointers as shown in the question. You could use simple cover functions, though, to do the job you want:

static int *addIntFunc(void *mem, size_t old_size, size_t extra_size)
{
return addElement(mem, old_size, extra_size);
}

int *(*addInt)(void *, size_t, size_t) = addIntFunc;

You probably can't usefully inline the function; a function pointer must point at a function.

Or, indeed, you could simply make use of addIntFunc (possibly renamed to addInt) to get the required effect, and then an inlined function might well be useful.

Error with function pointer returning a (void *)

Your declaration is wrong. The error message makes sense, since foo, as you wrote it, is declared to be a type alias for "pointer to function receiving void * and returning a function that receives int and returns void *.

If the function receives a void * and an int, you should have this instead:

typedef void *(*foo)(void *, int);

This essentially translates to "Let foo denote the type pointer to function receiving a void * and an int and returning a void *"



Related Topics



Leave a reply



Submit