function pointers with void* argument casting - c++

I have no idea on how to look this up, even the title is confusing, even I am confused about what I'm looking for, and the question has for sure already been asked but it's so specific to be found, so here a bit of context:
int comparison(const int* a, const int* b) {
return *a - *b;
}
int main(int argc, char const *argv[])
{
int arr[3] = {1,6,-2};
qsort(arr,3,sizeof(int),comparison);
return 0;
}
Well, it does work, but the compiler gives me a warning, because qsort wants a function of type:
int(*)(const void*, const void*)
and comparison is a function of type:
int(*)(const int*, const int*)
I want to know why the compiler is not happy because it just has to cast the address. It should even be happy to give a type to a void* pointer. Is this really bad? Like an undefined behavior or something? Or just the compiler whining about nothing much?

After other reasons already given, there's another one. Historically there were platforms for which void * and int * had different bit arrangements, I've heard rumor of one where void * and int * were different sizes. That function pointer cast won't always work.
const int *ia = (const int *)a;
const int *ib = (const int *)b;
might not compile away to ia = a; but rather to something like ia = a >> 1; So there's really got to be a place for those instructions to be.

why he (the compiler) is not happy .
qsort() expects a function point of type int (*)(const void *a, const void *b), not int (*)(const int *a, const int *b). The compiler could guess its OK and beform a cast, yet it is more productive for the compiler to warn about such problems.
Or just the compiler whining about nothing much?
By warming you, you are allowed to determine the degree of the problem.
In addition to #Alex Reynolds good answer, note that *a - *b may overflow, resulting in the wrong comparison.
Instead:
int comparison(const void *a, const void *b) {
const int *ia = (const int *)a;
const int *ib = (const int *)b;
return (*ia > *ab) - (*ia < *ib);
}
Good compilers recognize the (p>q) - (p<q) idiom and emit efficient code.

The qsort function takes as one of its arguments a function of a type you are not passing. So you'll need to change that.
Inside the comparator, you can recast the pointers to the desired type.
Additionally, you need to dereference the values of the const int pointers you are passing into the comparator function:
#include <stdio.h>
#include <stdlib.h>
static int
comparator(const void *a, const void *b)
{
return *(const int *)a - *(const int *)b;
}
static void
printArr(int arr[], int n)
{
int i;
for (i = 0; i < n; ++i) {
printf("%d ", arr[i]);
}
}
int
main(int argc, const char **argv)
{
int arr[3] = {1, 6, -2};
qsort(arr, 3, sizeof(int), comparator);
printArr(arr, 3);
return EXIT_SUCCESS;
}

Related

C/C++ build a generic stack frame to call different callback functions

I'm refactoring a C++ application that refers to a bunch a multiple callback functions, each having a different number of arguments and I would like to know if there's a generic way to build a dedicated argument stack frame before calling each of them.
In other words: fetching all required arguments first according to function to be called, then perform a call that would be transparent for called function.
In a way, this is the opposite of a variadic function, as this would be a single function that knows it can receive different number of arguments. Here I have a bunch of immutable, regular functions and I'd like to call them from a generic hub.
I place both C and C++ tags here because I'm interested in propositions for both these languages, I have the feeling that what would work for C would also be applyable to C++ and I'm still open to "C++ only" solutions such as variadic templates or such.
The background of all of it is that quoted program is actually parsing a command line, then calling a function according to the name of the command, passed as first argument after program name, then all required ones as plain strings, but depending of invoked command.
I know I could write something like:
if(nb_of_args == 1)
my_callback_ptr(argv[n]);
else if (nb_of_args == 2)
my_callback_ptr(argv[n],argv[n+1]);
else if (nb_of_args == 3)
my_callback_ptr(argv[n],argv[n+1],argv[n+2]);
else if (nb_of_args == 4)
my_callback_ptr(argv[n],argv[n+1],argv[n+2],argv[n+3]);
else if…
…to restrict the compiled calls to the sole number of arguments regardless of the function itself, but I'd still like to do better.
Thanks in advance to everybody.
A viable approach is to implement dispatch table that will contain pointers to wrapper functions automatically passing appropriate amount of arguments to each callback.
#include <array>
#include <utility>
#include <cstddef>
template<auto x_p_callback, ::std::size_t... x_indexes>
void invoke_callback(char const * const * const pp_args, ::std::index_sequence<x_indexes...>)
{
(*x_p_callback)(pp_args[x_indexes]...);
}
template<typename x_Callback >
struct
t_ArgsCount;
template<typename x_Result, typename... x_Args>
struct
t_ArgsCount<x_Result (x_Args...)>
: ::std::integral_constant<::std::size_t, sizeof...(x_Args)>
{};
template<auto x_p_callback>
void callback_sunk(char const * const * const pp_args)
{
using
t_Callback = typename ::std::remove_reference<decltype(*x_p_callback)>::type;
using
t_Sequence = typename ::std::make_index_sequence<t_ArgsCount<t_Callback>::value>;
invoke_callback<x_p_callback>(pp_args, t_Sequence{});
}
using
t_Callback = void (char const * const * const pp_args);
template<auto... x_p_callbacks>
constexpr auto make_table(void)
{
return ::std::array<t_Callback *, sizeof...(x_p_callbacks)>{&callback_sunk<x_p_callbacks>...};
}
void my_callback_0() {}
void my_callback_1(char const *) {}
void my_callback_2(char const *, char const *) {}
void my_callback_3(char const *, char const *, char const *) {}
int main(int argc, char const * const * const pp_args)
{
constexpr auto table{make_table<my_callback_0, my_callback_1, my_callback_2, my_callback_3>()};
table.at(argc)(pp_args);
}
online compiler
Although I have some doubts about the C code I wrote (all to be verified). To solve the difficulty to convert your callbacks with a prototype like callback(int argc, char *argv[] (as the C/C++ main), my idea has been to make the pointers into the functions table that indexes the callbacks as pointers to variadic functions.
In this way we may call all callback functions passing the maximum number of parameters by means the pointers in the table. Obviously the called functions will only use the parameters they need and not the others.
On the other hand, this code will consume instructions and, depending on the case, even stack memory to pass useless parameters to functions that do not need them.
This code seems to run correctly, but it has to be verified!
#include <stdio.h>
#define CBCALL(cbidx, argv, n) \
ft[cbidx].f(argv[n],argv[n+1],argv[n+2],argv[n+3],argv[n+4])
int cb0();
int cb1(char *);
int cb2(char *, char *);
int cb3(char *, char *, char *);
int cb4(char *, char *, char *, char *);
int cb5(char *, char *, char *, char *, char *);
typedef int FN(char *,...);
struct table {
FN * f;
} ft[]={
{(FN *)cb0},
{(FN *)cb1},
{(FN *)cb2},
{(FN *)cb3},
{(FN *)cb4},
{(FN *)cb5}
};
int main(int argc, char * argv[])
{
if (argc<7) {
CBCALL(argc-1,argv,1);
if (argc>2)
{// Trying with copied parms and NULL.
char *xarg[5];
xarg[0]=argv[1];
xarg[1]=argv[2];
xarg[2]=NULL;
xarg[3]=NULL;
xarg[4]=NULL;
CBCALL(2,xarg,0);
}
} else {
printf("Max 5 parameters are allowed!\n");
}
return 0;
}
int cb0()
{
printf("No parms\n");
return 0;
}
int cb1(char *a)
{
printf("%s\n",a);
return 1;
}
int cb2(char *a, char *b)
{
printf("%s %s\n",a,b);
return 2;
}
int cb3(char *a, char *b, char *c)
{
printf("%s %s %s\n",a,b,c);
return 3;
}
int cb4(char *a, char *b, char *c, char *d)
{
printf("%s %s %s %s\n",a,b,c,d);
return 4;
}
int cb5(char *a, char *b, char *c, char *d, char *e)
{
printf("%s %s %s %s %s\n",a,b,c,d,e);
return 5;
}

Function that returns max element of an array of different types

I have couple of compare function that go something like this:
int greater_than_int(const void *a, const void *b) {
if (*(int *)a > *(int *)b) return 1;
return 0;
}
and a max function that goes like this:
const void* max(const void *base, size_t members, size_t size,
int (*compar)(const void *, const void *)) {
char *base_ptr = (char *) base;
char max = *base_ptr;
for(int i = 1; i < nmemb; i++) {
if (compar(&(*(base_ptr + i*size)), &max) != 0) {
max = *(base_ptr + i*size);
}
}
return &max;
}
When I try to run this function with greater_than_int I get nonsense results and since I'm still pretty new with C++ I'm not sure why. Any help would be appreciated.
Edit: I've changed some things to my code but now it always returns max as 0. Still trying to figure out why, I appreciate all the people saying that this isn't the best way to do this but, unfortunately, this is the way that I have to do this.
Since you're forced to work with those function signatures, here's one way of dealing with them.
// I suggest changing this to `bool`, but you can leave it as `int` if you must
bool greater_than_int(const void *a, const void *b) {
// no need for `if(...)` - just return the result of the comparison
return *static_cast<const int*>(a) > *static_cast<const int*>(b);
}
Then, the actual max function has some problems where you define max as a char and not a pointer etc. max can be left as a const void* since you don't need to perform any pointer arithmetics with it. I'm using base as the pointer to the maximum element below instead.
#include <iterator> // std::next, std::advance
const void* max(const void *base, size_t nmemb, size_t size,
bool (*compar)(const void*, const void*)) // note: bool here too
{
if(nmemb) {
// no need to cast away const:
auto current = static_cast<const char*>(base);
auto end = std::next(current, nmemb * size);
for(std::advance(current, size); current != end;
std::advance(current, size))
{
if(compar(current, base)) base = current;
}
}
return base;
}
Demo

How to define pointer to pointer to function and how to use it in C++?

My question is how to translate the following example? Is this a function, that returns int pointer?
int* (*function)(int, (int (*k)(int *)));
And can I can't write program that use it?
Thanks in advance!
It is a function-pointer
The function returns a pointer to an int
The function's first arg is an int
The function's second arg is a function-pointer k
k returns an int
k takes a pointer to an int as argument
Sure you can use that in your program. It is not too unusual. There are much worse declarations i have seen.
I renamed your "function" to "F" for clarity. Then you can write:
int* (*F)(int, int (*kFunc)(int *) );
Alternative:
typedef int (*kFunc)(int *);
int* (*F)(int, kFunc);
There are a lot of ways to use pointer to a function, may be a pattern such as Factory could take advantage of the function pointer to create new objects.( Look here : http://www.codeproject.com/Articles/3734/Different-ways-of-implementing-factories)
May be this piece of code could help you and give ideas of how powerfull can be working with function pointers.
#include <stdio.h>
#include <stdlib.h>
#include <map>
// Define the func ptrs
typedef void (*TFunc)(const char *, int);
typedef int (*TFunc2)(int);
int return_value(int i)
{
return i * 5;
}
void a( const char *name, int i )
{
printf ("a->%s %d\n\n", name, i);
}
void b( const char *name, int i)
{
printf ("b->%s %d\n\n", name, i);
}
struct test
{
const char *name;
int i;
TFunc func;
};
static test test_array[2] =
{
{ "a", 0, a },
{ "b", 1, b },
};
int main(int argc, char **argv, char** envp)
{
// Check the simple case, pointer to a function
TFunc fnc = a;
TFunc2 fnc2 = return_value;
fnc("blabla", 5);
fnc = b;
fnc("hello!", 55);
printf ("%d\n\n",fnc2(5));
//Check arrays of structs when there is a pointer to a fnc
test_array[0].func(test_array[0].name, test_array[0].i);
test_array[1].func(test_array[1].name, test_array[1].i);
//Handle a map of functions( This could be a little implementation of a factory )
typedef std::map<int, TFunc > myMap;
myMap lMap;
lMap.insert(std::make_pair(5, a));
lMap.insert(std::make_pair(2, b));
if( lMap.find( 5 ) != lMap.end() )
{
lMap[5]("hello map 5", 1);
}
myMap::iterator lItFind = lMap.find(2);
if( lItFind != lMap.end() )
{
lItFind->second("hello map 2", 2);
}
return(0);
}
I hope that this helps you.
You should remove extra parentheses, this is correct version:
int* (*function)(int, int (*k)(int *));
explanation (using right-left rule):
int* (*fn)(int, int (*k)(int *));
fn : fn is a
(*fn) : pointer
(*fn)(int, int (*k)(int *)) : to a function taking as arguments
- an int and
- function pointer
which takes a pointer to int
and returns int
int* (*fn)(int, int (*k)(int *)) : and returns a pointer to int
below is a short example on how to use it, also you ask for How to define pointer to pointer to function so below this is also included.
http://coliru.stacked-crooked.com/a/d05200cf5f6397b8
#include <iostream>
int bar(int*) {
std::cout << "inside bar\n";
return 0;
}
int* foo(int, int (*k)(int *)) {
std::cout << "inside foo\n";
k(nullptr);
return nullptr;
}
int main() {
int* (*function)(int, int (*k)(int *));
function = foo;
function(0, bar);
// Now, as you asked for, a pointer to pointer to above function
decltype(function) *pff;
pff = &function;
(*pff)(0, bar);
}

C++, what is the purpose of argument type (void*&)?

I am trying to understand a certain code where I found something hard to understand for me.
void BPlusTree::GetKey(int key, void*& keyloc) const {
keyloc = keys + key * attrLength;
return 0;
}
This function calculates the location (memory address) of the key value and store it at keyloc variable.
void*& means the reference for a void pointer.
And here reference is used to reflect the changed value of keyloc to the outer function which called `GetKey.
Am I right till now?
So I thought that, in the main function, when it calls GetKey function. It needs to pass (void*) not the (void*&).
int main() {
.....
int currPos = 0;
char* key = NULL;
int result = currNode->GetKey(currPos, (void*&) key);
}
Why is (void*&) used instead of (void*) here?
Thank you.
// And I added here example code...
#include <regex>
#include <iostream>
#include <stdlib.h>
using namespace std;
#include <stdio.h>
void foo(int &a, int &b) {
a = 10;
b = 20;
}
void foo2(int* &c, int* &d) {
*c = 10;
*d = 20;
}
void foo3(void* &c, void* &d) {
*(int*)c = 10;
*(int*)d = 20;
}
int main(void) {
int a = 0;
int b = 0;
int* c = new int;
int* d = new int;
void* e = malloc(sizeof(int));
void* f = malloc(sizeof(int));
foo(a, b);
printf("A is %d and B is %d\n", a, b);
foo2(c, d);
printf("C is %d and D is %d\n", *c, *d);
foo3((void*&)c,(void*&) d); // It works fine
printf("C is %d and D is %d\n", *c, *d);
foo3((void*)c,(void*) d); // But it does not work
printf("C is %d and D is %d\n", *c, *d);
}
Is the (void*) problematic one?? :D
Yes, you're pretty much right in what you do understand. For the last bit, perhaps it'll be easier to use a pointer instead of a reference in explaining...
You could have had
void BPlusTree::GetKey(int key, void** keyloc) const { ... };
and a caller
char* key = NULL;
int result = currNode->GetKey(currPos, (void**) &key);
Here, it should be obvious why you cannot use &(void*) key: (void*) key is an rvalue, and you cannot take its address. It'd be like taking the address of (key + 0). Sure, key + 0 is always just key, but the mere fact that you have an addition there means you're looking at a copy of the pointer value, not the original pointer object.
When dealing with references, there is not an explicit "address of" operation like there is with pointers, but the problem is the same. GetKey(currPos, (void*) key) doesn't work because (void*) key is an rvalue, not an lvalue. (void*&) key casts key to "reference to void*", and pretty much means *(void**) &key. It is done to pretend that key was actually defined as void*.
Note: this is generally considered very bad practice. key would be better actually defined as void*, and then no cast is required to call GetKey.

casting in qsort()

The below program sorts all the suffices of a string using qsort() library function.
int sacomp(const void *a, const void *b)
{
return strcmp(*(const char**)a, *(const char**)b); <------------
}
void sort(string s)
{
int size = s.size();
char const *data = s.c_str();
char const **sa = new char const *[size+1];
for(int i = 0; i < size; i++)
sa[i] = data+i;
qsort(sa, size, sizeof(sa[0]), sacomp); // O(n * Lon n)
}
int main()
{
string s("ABCCCDEFABBABBA");
sort(s);
return 0;
}
I am not able to understand the casting done in the sacomp() method.
strcmp(*(const char**)a, *(const char**)b);
Why a is casted to const char** and then being de-referenced?
qsort passes pointer of elements. You passed sa as char**, so every element is char*, and qsort passes char**, finally you got char** in the sort function.
Your element is char *, therefore you should change void on char * and get pointer to char *, which is char **. Meanwhile strcmp needs char *.