Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this pointer to function work without warnings or errors?

Tags:

Knowing that this call:

pow(4); 

will generate this error message:

 error: too few arguments to function ‘pow’ 

I am learning pointers to functions and I got surprised when seen this code below working. But why?

#include<stdio.h> #include<math.h>  void aux(double (*function)(), double n, double x);  int main(void) {     aux(pow, 4, 2);       aux(sqrt, 4, 0);      return 0; }  void aux(double (*function)(double), double n, double x) {        if(x == 0)         printf("\nsqrt(%.2f, %.2f): %f\n", n, x, (*function)(n));       else         printf("\npow(%.2f, %.2f): %f\n", n, x, (*function)(n));   } 

I compiled using:

gcc -Wall -Wextra -pedantic -Wconversion -o test test.c -lm 

The result is:

pow(4.00, 2.00): 16.000000  sqrt(4.00, 0.00): 2.000000 

If I change the third parameter of the first call of aux to 3, the result changes to:

pow(4.00, 3.00): 64.000000  sqrt(4.00, 0.00): 2.000000 

And one more question. What is the correct way to declare and use pointers to functions in this case?

like image 430
ViniciusArruda Avatar asked Feb 02 '15 16:02

ViniciusArruda


People also ask

How does pointer to a function work?

A pointer to a function points to the address of the executable code of the function. You can use pointers to call functions and to pass functions as arguments to other functions. You cannot perform pointer arithmetic on pointers to functions.

What is the problem of function pointer?

Function pointer casts can cause function pointer calls to fail. This may be related to a function pointer cast problem as implicit declarations may have a different type than how you call them. However, in general the compiler cannot warn about this, and you will only see a problem at runtime.

Why do we use pointers to functions in C?

In C, we can use function pointers to avoid code redundancy. For example a simple qsort() function can be used to sort arrays in ascending order or descending or by any other order in case of array of structures. Not only this, with function pointers and void pointers, it is possible to use qsort for any data type.

What Cannot be done with function pointer?

What will we not do with function pointers? Explanation: As it is used to execute a block of code, So we will not allocate or deallocate memory.


1 Answers

This:

void aux(double (*function)(), double n, double x); 

uses an old-style non-prototype declaration for function. The empty parentheses () mean that the function takes a fixed but unspecified number and type(s) of arguments.

C still permits this kind of declaration for backward compatibility. Prototypes (function declarations that specify the types of the parameters) were introduced by ANSI C in 1989. Prior to that, it was not possible to specify parameter types in a function declaration, and compilers could not check whether a call passed the correct number and type(s) of arguments.

Such declarations are "obsolescent", meaning that support for them could be removed from a future C standard (but in more than 20 years the committee hasn't gotten around to removing them). Calling a function with the wrong number of types of arguments will not necessarily be diagnosed by the compiler, and the behavior is undefined.

The rules for compatibility of function types are a bit complicated when one has a prototype and the other doesn't. These types:

double(double)         /* function with one double parameter                           returning double */ double(double, double) /* function with two double parameters                           returning double */ 

are not compatible with each other, but they're both compatible with this type:

double()   /* function with a fixed but unspecified number of parameters               returning double */ 

which is what makes it possible to have incorrect calls without a diagnostic from the compiler.

To avoid this problem, always use prototypes:

void aux(double (*function)(double, double), double n, double x); 

Not only do you get better diagnostics from your compiler, you don't have to worry about the convoluted compatibility rules for non-prototyped functions (which, if you're curious, are specified in N1570 6.7.6.3 paragraph 16).

like image 97
Keith Thompson Avatar answered Nov 27 '22 15:11

Keith Thompson