Asking the syntax of Function pointer. - int (int) - c

I've learned function pointer is used as :
double (*ptr)(double)
ptr = my_func1;
And also, using 'typedef' could be
typedef double (*func1)(double);
func1 my_func1;
But I can't understand why this code is valid below :
int main(void){
test(a);
}
void test(int f(int))
{\
int x;\
(f==a)?(x=1):(x=2);\
printf("%d",f(x));\
}
What's that int f(int)? Is it same syntax with function pointer?
I know the type int (*)int is valid, but I've never seen the type int (int).
And Also I can't understand why the syntax in the main fuction "int f(int) = func_1" is invalid but in the 'test' function's parameter int f(int) = a is valid.
Please tell me TT Thank you.

int f(int) is a function declaration.
In C, two kinds of entities cannot be passed into functions, returned from functions or assigned: arrays and functions.
If parameters of these types are declared, they are silently turned into pointers.
A parameter int f(int) is changed to mean int (*f)(int), similarly to the way a parameter int a[3] is changed to int *a.
You might see a gratuitous warning if you declare a function one way, but define it the other; e.g.:
void test(int (*)(int));
void test(int f(int))
{
}
I've seen some version of GCC warn about this, even though it is correct; the definition and declaration are 100% compatible.
Because inside test, f is declared as a pointer, it is assignable:
f = some_func
However, in a situation where int f(int) declares a function, the identifier is not assignable:
{
int f(int); // "There exists an external f function" -- okay.
f = some_func; // Error; what? You can't assign functions!
}
Outside of function parameter declarations, functions and pointers to functions are distinguished in the usual way, as are arrays and pointers.

Related

Defining a function through a pointer

I have the following code:
typedef void (*func_type)(int a, int b);
func_type func;
int main()
{
func = (func_type)GetProcAddress(NULL, "func");
}
This code works fine, but I would like to change func_type func; to void func(int a, int b); (because code completion shows "func_type" instead of "func" when typing the parameters).
But when I try to change this, the compiler tells me that in the main function "expression must be a modifiable lvalue". I tried to look online but did not find an answer to my problem.
Code becomes this:
typedef void (*func_type)(int a, int b);
void func(int a, int b);
int main()
{
func = (func_type)GetProcAddress(NULL, "func");
}
Functions in C behave similar to arrays. They both decay to pointers. Whenever function name is used it automatically decays to a pointer to this function. The exceptions are & and sizeof operators. Operator sizeof does not accept a function as operand. That is why foo and &foo are equivalent.
Functions itself are non-modifiable by design. Any attempt of modifying it i.e. by memcpy-ing to a function pointer is undefined behaviour.
Surprisingly, function call operator () does not take a function as operand but a pointer to a function.
Therefore, a function call
foo(1);
is actually
(&foo)(1);
Because foo decays to &foo before evaluation of the function call.
That is why one can interchangeably use functions and function pointer in function call operands.
void foo(int) { ... }
void (*bar)(int);
foo(1); // foo decays to &foo which is a function pointer
bar(2); // bar is already a function pointer
To solve the original problem I suggest keeping func be a function pointer, that initially points to some dedicated function but it can be overwritten later on:
typedef void func_type(int,int);
void default_func(int a, int b) { ... }
funt_type* func = default_func; // decays to &default_func !
int main()
{
func(1,2); // calls default_func
func = (func_type*)GetProcAddress(NULL, "func");
func(3,4); // calls func from dll/so
}
I've decided to use function types (not function pointer types) what is a bit un-orthodox. IMO, it make syntax more visually pleasing, and it is easier to parse by a human. Moreover, it is explicit about what is a pointer what is not.
typedef void (*func_type)(int a, int b); declares func_type to be a type that is a pointer to a function. Then func_type func; declares func to be a pointer. Your proposed alternative, void func(int a, int b); declares func to be a function.
Since you can assign to a pointer, func = …; works with the first declaration. Since you cannot assign to a function, func = …; does not work with the second declaration.
To declare func to be a pointer to a function without using a typedef, use void (*func)(int, int);.

why can not malloc in global but can use inline function for malloc [duplicate]

This question already has answers here:
Error "initializer element is not constant" when trying to initialize variable with const
(8 answers)
Closed 2 years ago.
Hi i have a test code for calling malloc as below:
#include <stdio.h>
#include <stdlib.h>
int *p;// = (int*)malloc(sizeof(int));
int main() {
//...
}
Of course this code will be fail when compile with the error: initializer element is not constant and i have referenced this question: Malloc function (dynamic memory allocation) resulting in an error when it is used globally. They said that we have to use malloc() in side a function. But if i change my code to:
#include <stdio.h>
#include <stdlib.h>
int *p;
static int inline test_inline(int *x) {
printf("in inline function \n");
x = (int*)malloc(sizeof(int));
return x;
}
test_inline(p);
int main(){
//...
}
As the definition of inline function: "Inline Function are those function whose definitions are small and be substituted at the place where its function call is happened. Function substitution is totally compiler choice." So this mean we can substitute the inline function test_inline in above example with the code inside it and it means we have call malloc() in global ? Question 1: is this wrong about inline or malloc() ?
Question 2: In the link i give about malloc function dynamic there is an answer said that "Not only malloc, u can't call any function as you have called here. you can only declare function as global or local there" but i see that we still can call function in global and in global we can initialization not only declaration as below:
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1;
int test() {
printf("hello");
}
test();
int main() {
//...
}
So this mean in the global we still can declaration and initialization and call function. But when we compile the above code it has a warning that warning: data definition has no type or storage class So why we have this warning with variable b ? I do not see any thing which inconsequential here. And with the line test(); i have call a function outside main(), i know this make no sense because we never run test() but i have no problem, stil build success. So back to question 1 about the malloc(), i think with the answer that "we can not call a function in global or can not initialize", i think it is not true. Is there any explain more reasonable?
Please refer to the comments.
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1; //this is only allowed, because the previous line is a tentative definition. [1]
int test() {
printf("hello");
}
test(); // this is taken as a function declaration, not a function call [2]
int main() {
//...
}
Case [1]:
Change you code to
int b = 5; // not a tentative defintion.
b = 1; // this assignment is not valid in file scope.
you'll see an error.
Case [2]:
If the signature of the function differs, you'll again see an error. Example: try the below:
float test( int x ) {
printf("hello");
return 0.5;
} //return changed to float, accepts an int as paramater.
test(); //defaults to int and no parameter - conflict!!
this will produce the error for conflicting types.
So, bottom line, no assignment, function call - all in all, no code that needs to execute at runtime, can be put into file scope. The reason behind that being, unless it's contained in a function that's called from main(), there's no way to know when / how to execute it.
You're not calling functions "globally".
Taking your example:
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1;
int test() {
printf("hello");
}
test();
int main() {
//...
}
In C types default to int.
So the lines
int b;
b = 1;
are basically
int b;
int b = 1;
and the lines
int test() {
printf("hello");
}
test();
are just
int test() {
printf("hello");
}
int test(); // -> this is just a matching declaration
Have a look at:
https://godbolt.org/z/3UMQAr
(try changing int test() { ... to char test() { ... and you get a compiler error telling you that those types don't match)
That said, you can't call functions there. Functions are called at runtime by your program (especially malloc, which is asking your OS to allocate memory for you). I'm not a C expert here but as far as I know C doesn't have constexpr functions, which would be the only "exception".
See: Compile-Time Function Execution
Question 1: is this wrong about inline or malloc()
kind of: malloc does have to be called in a function, but the variable it works on can be declared global. i.e. int *pointer = NULL;//global scope
then pointer = malloc(someByteCount);//called within function. Now, pointer is still global, but also has a memory address pointing to someByteCount bytes of memory.
Question 2: In C, all functions are defined on the same level of a .c file, just like main(void){...return 0}, but all functions (except main(void)) must be called within the {...} of other functions, so in short, functions cannot be called from global space.
Illustration for Q2:
//prototypes
void func1(void);
void func2(void);
void func3(void);
int main(){
int val = test_inline(p);//...
}
int main(void)
{
//legal
func1();
func2();
func3();
return 0;
}
//not legal
func1();
func2();
func3();
//definitions
void func1(void)
{
return 0;
}
void func2(void)
{
return 0;
}
void func3(void)
{
return 0;
}
Errors in syntax of your example (see comments):
int *p = NULL;//initialize before use
static int inline test_inline(int *x) {
printf("in inline function \n");
x = (int*)malloc(sizeof(int));
printf("%p\n", x);
return 0;
//return x;//function returns int, not int *
}
//... test_inline(p);//must be called in a function
int main(void){
int val = test_inline(p);//function declaration returns int, not pointer
return 0;
}
This code compiles, and runs, but as noted in comments, usefulness may be lacking.
Question 1: is this wrong about inline or malloc() ?
Neither. Your understanding of inline is incorrect. The function call may be replaced with an inline expansion of the function definition. First, let's fix the function definition because the return type int doesn't match the type of what you're actually returning:
static inline int *test_inline( int *x )
{
printf( "in inline function\n" );
x = malloc( sizeof *x );
return x; // x has type int *, so the return type of the function needs to be int *
}
If you call this function like so:
int main( void )
{
int *foo = test_inline( foo );
...
}
what the compiler may do is substitute the function call with the assembly language equivalent of the following:
int main( void )
{
int *foo;
do
{
printf( "in inline function\n" );
int *x = malloc( sizeof *x );
foo = x;
} while( 0 );
...
}
Nothing's happening "globally" here. The substitution is at the point of execution (within the body of the main function), not at the point of definition.
Question 2: In the link i give about malloc function dynamic there is an answer said that "Not only malloc, u can't call any function as you have called here. you can only declare function as global or local there" but i see that we still can call function in global and in global we can initialization not only declaration as below:
In the code
int test() {
printf("hello");
}
test();
the line test(); is not a function call - it's a (redundant and unnecessary) declaration. It does not execute the function.
Here are some excerpts from the language definition to clarify some of this:
6.2.4 Storage durations of objects
...
3 An object whose identifier is declared without the storage-class specifier
_Thread_local, and either with external or internal linkage or with the storage-class
specifier static, has static storage duration. Its lifetime is the entire execution of the
program and its stored value is initialized only once, prior to program startup.
Bold added. Any variable declared outside the body of a function (such as p in your first code snippet) has static storage duration. Since such objects are initialized before runtime, they cannot be initialized with a runtime value (such as the result of a function call).
6.7.4 Function specifiers
...
6 A function declared with an inline function specifier is an inline function. Making a
function an inline function suggests that calls to the function be as fast as possible.138)
The extent to which such suggestions are effective is implementation-defined.139)
138) By using, for example, an alternative to the usual function call mechanism, such as ‘‘inline
substitution’’. Inline substitution is not textual substitution, nor does it create a new function.
Therefore, for example, the expansion of a macro used within the body of the function uses the
definition it had at the point the function body appears, and not where the function is called; and
identifiers refer to the declarations in scope where the body occurs. Likewise, the function has a
single address, regardless of the number of inline definitions that occur in addition to the external
definition.
139) For example, an implementation might never perform inline substitution, or might only perform inline
substitutions to calls in the scope of an inline declaration
All this means is that the inlined code behaves like it was still a single function definition, even if it's expanded in multiple places throughout the program.

Is it possible to provide a function name as an initializer in another function's definition?

We can provide an object as an initializer in another object's definition. It just copies and assigns the value of an object to another.
Is it possible to provide a function name as an initializer in another function's definition?
Where does the C standard say if it is allowed or not? I didn't find it, so I suppose it is possible.
The following two examples will result in syntax error:
#include <stdio.h>
int f(){};
int main()
{
int (g=f)();
int h() = f;
}
Thanks.
You probably want a function pointer (as a function doesn't really make sense in this context):
int (*h)() = f;
No. Function declarations can't have an initializer.
If you want to ensure type compatibility, you can use a function typedef.
typedef int f_tp(void);
f_tp f, h; //check f and h for compatibility with int (*)(void)
int f(){} //✓
//will get an error here because h was declared f_tp h == int h(void);
void h()
{
}

Returning Void Pointer Truncates Value

I'm having trouble returning a void pointer to another function in C.
HEADER FILE:
void *function2( void );
MAIN.C
#include "myHeader.h"
void function1 (){
void *temp = NULL;
temp = function2();
}
FUNCTION2.C
int a = 3;
void *function2(void){
printf("Memory Address %p\n",&a );
return (void *) &a; // value of &a is 0x100023444
}
However, the value of temp in function1() is 0x3444,instead of 0x100023444.
Does anyone know a solution for this, or if I am doing something wrong?
EDITED:
It seems, the header was added in the wrong place, leading to the problem described by AndreyT and Jonathan below, which seems to have fixed the truncation problem. Thanks for your help guys!
Given the revision to the question, I'm confident the problem is that you did not declare function2() before you used it. Consequently, the compiler thinks it returns an int, not a void *. It should also be complaining about the actual definition not matching the assumed declaration.
You should make sure your compiler options require you to define or declare a full prototype for each function before you use it.
Note that you should declare void *function2(void); because omitting the void in the parameter list means something quite different — it means the compiler is not told anything about what parameters it takes, not that it takes no parameters. (This is a difference from C++.)
You still have problems because you're returning a pointer to a local variable. You can probably print the pointer (though even that is not guaranteed by the standard), but you cannot reliably use it.
extern void *function2(void);
void function1(void)
{
void *temp = function2();
printf("Address: %p\n", temp);
}
void *function2(void)
{
int a = 3;
printf("Address: %p\n", &a);
return &a; // value of &a is 0x1200001234
}
Or define function2() before defining function1().
Note that it is crucial to include the header both where the function is defined (to make sure the definition is consistent with the header) and where the function is used (to make sure the use is consistent with the header). As long as you do this, all will be well.
Inside function1 you are calling a yet-undeclared function function2. In classic C language (C89/90) this is allowed, but an undeclared function is assumed to return an int. Apparently, on your platform pointers are 64 bits wide and int is 32 bits wide. This is what causes a truncation of your 64-bit pointer value 0x1200001234 to 32 bits, giving you 0x1234.
Formally, your code has undefined behavior, since after causing the compiler to assume that function2 returns int you declared it as returning void *. Even C89/90 compilers usually issue a warning about this problem (and C99 compiler report an error). Did you ignore it?
Either move the entire definition of function2 up and place it above function1
void *function2(void) {
int a = 3;
return &a;
}
void function1 (void){
void *temp = NULL;
temp = function2();
}
Or, alternatively, declare function2 before calling it
void *function2(void);
void function1(void) {
void *temp = NULL;
temp = function2();
}
void *function2(void) {
int a = 3;
return &a;
}
You have to declare your functions before you call them (preferably with prototype).
This answer is apart from truncation.
In function2() a is local variable. Here scope and lifetime od a limited to the function2. So returning the address to other function is illegal. It will cause undefined behavior. Please pay more attention to learn storage class in C

Is main with parameter list of void different from main with an empty parameter list? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is the type of the main function in C and c++ left to the user to define?
What is a void ? Anyone provide some examples, proper use of void ? And what is the difference when we write void main (void) or main() ?
In C, in general, (void) means no arguments required in function call, while () means unspecified number of arguments.
e.g.
void foo(void)
{
// body
}
void bar()
{
//body
}
In calling enviroment,
foo(); // Correct
foo(1); // Incorrect
bar(); // Correct
bar(1); // Also correct
This was the general explanation.
But for your case for main() , C99 Standard says that,
5.1.2.2.1 Program startup
The function called at program startup is named main. The
implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or
with two parameters (referred to here as argc and argv, though any
names may be used, as they are local to the function in which they are
declared):
int main(int argc, char *argv[]) { /* ... */ } or equivalent;
or
in some other implementation-defined manner.
So, in this void main(void) return type should be int.
And at last , for main(),
return type is not given so implicitly return type would be int.
Excluding the return type of the main as in
main(){
}
doesn't mean that it's a void type, it depends on the compiler. I think it can be said it's generically interpreted as
int main(){
}
The void type tells the compiler that there is no 'entity' (no 'storage'), so
void func(int i)
takes an int but returns nothing. In the case of parameters this:
void func()
is equivalent to this:
void func(void)
which indicates more explicitly that it does not take parameters.
Different story is with the type void * which is a type, a pointer to something dimensionless.
Basically, void is a data type, which basically used with method declaration. It means nothing or no type. Eg:
1) int myFunc(void) -- the function takes nothing.
2) void myFunc(int) -- the function returns nothing
3) void* data; -- 'data' is a pointer to data of unknown type, and cannot be dereferenced
Void means "emptyness". In your example of void main() it means that the functions main() does not return a value. I feel obliged tell you that void main() should be avoided (no pun intended) at all costs, use int main() instead. int main() makes sure your program can return a value of type int to the OS on close. There are numerous other uses of void, check out this website if you want to read more about this.
void is a data type with no values. It is also an incomplete data type that cannot be completed. When used as a return type for a function, it indicates that the function does not return a value:
void foo(int x);
When used as a parameter list, it indicates that the function takes no arguments:
void bar(void);
This is different from an empty parameter list, which indicates that the function takes an unspecified number of arguments (in C; in C++, an empty parameter list is the same as using void):
void bletch();
No object (variable) can be typed void. However, you can declare pointers of type void *: these are "generic" pointers, and can be converted to and from other pointer types without an explicit cast. The standard memory allocation functions malloc, calloc, and realloc all return void *:
double *darr = malloc(sizeof *darr * rows);
In a hosted implementation (basically, anything with an operating system), main must be declared as
int main(void)
or
int main(int argc, char **argv) // the parameter names can be whatever you want,
// but argc and argv are the usual convention;
// char **argv is equivalent to char *argv[]
or in some other implementation-defined manner; an implementation may accept
void main()
as a legitimate signature for main, but it must explicitly document that somewhere.

Resources