I found these work types of code:
hash_init.key = &hash_key_lc;
And
ls->handler = init_connection;
Here both hash_key_lc and init_connection are functions,but one is with & the other not,why?
UPDATE
so they are the same thing,but what's the rational??
This is identical to the following question:
In C, what is the difference between `&function` and `function` when passed as arguments?
The accepted answer there:
There is no difference. For evidence
see the C99 specification (section
6.7.5.3.8).
"A declaration of a parameter as
‘‘function returning type’’ shall be
adjusted to ‘‘pointer to function
returning type’’, as in 6.3.2.1."
reference/deference on a function is treated as a language special case in c,as function deserves this kind of special case ,it can't be passed by a certain value,you can only pass it by address/reference.
See C99 section 6.3.2.1, §4:
A function designator is an
expression that has function type.
Except when it is the operand of the
sizeof operator or the unary &
operator, a function designator with
type ‘‘function returning type’’ is
converted to an expression that has
type ‘‘pointer to function returning
type’’.
Thus, if foo is a function, the expressions foo and &foo are mostly interchangeable, in particular
foo == &foo
This is similar to how expressions with array type are implicitly converted to expressions with pointer type. Also, if fp is a function pointer, you can call it with or without dereferencing, ie the expressions
(*fp)(42)
and
fp(42)
are equivalent. Function calls are actually defined in terms of function pointers (section 6.5.2.2 §1) and not function designators, ie as far as language semantics go, *fp in the first example will implicitly converted back to fp before the parens are applied.
Related
Is this valid C99 code? (I guess I'm asking whether it's portable)
void test(void){
return;
}
void (*fp)(void) = test;
if (fp == test){ <--- This line
printf("Success\n");
}
I gather only pointers of the same type can be compared with one another, so maybe my question is whether function names like 'test' are just pointer aliases? Or maybe someone can tell me what my question is better than I can :)
The code is valid ANSI C.
Actually what happens is, a function name such as test in your code, is automatically converted to a pointer to function.
You could change test to &test, the result is the same.
Yes, it is fine. The C standard is pretty self-explanatory in this case (C11 6.3.2.1/4):
A function designator is an expression that has function type. Except when it is the
operand of the sizeof operator, or the unary & operator, a function designator with
type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’.
In your case test is an expression with function type. It gets converted to a function pointer of void(*)(void) type. This is a compatible pointer type with fp, so the == operator allows it.
Regarding the equality operator ==, the standard says (C11 6.5.9, emphasis mine):
Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function,
Is it purely style that you can declare a function-reference parameter like,
int g ( int (*f)(int,int) ) {
Or
int g ( int f(int,int) ) {
In my limited experience with C, I've never seen the prototype-method.
I suppose it is style, but the explicit pointer to function notation aligns with ancient practice and with the way the compiler interprets the code.
The C11* standard says in §6.7.6.3 Function declarators (including prototypes) ¶8:
¶8 A declaration of a parameter as "function returning type" shall be adjusted to "pointer to function returning type", as in 6.3.2.1.
And §6.3.2.1 Lvalues, arrays and function designators ¶4 says:
¶4 A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, the _Alignof operator,65) or the unary & operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type".
65) Because this conversion does not occur, the operand of the sizeof or _Alignof operator remains a function designator and violates the constraints in 6.5.3.4.
Using the pointer notation, therefore, shows explicitly what the compiler will do anyway. (I still usually invoke explicit pointers to functions using the (*function_ptr)(arg1, …, argN) notation, even though function_ptr(arg1, …, argN) also works.)
* The C18 standard is current, but there isn't a convenient online HTML version of it available as yet. Mostly, the two are very similar. As it happens, §6.3.2.1 ¶4 is one paragraph with a difference — the C18 version doesn't mention _Alignof.
The name of a function f IS a pointer to function f. ie the compiler treats them identically. You can use the 2 forms interchangeably, in the context of your questions.
However, in the interest of completeness, see the exceptions in cases of sizeof operator, the _Alignof operator,65) and the unary & as correctly pointed out in Jonathan Leffler's most complete answer.
Both of your statements say:
g is a function returning int, whose parameter is a pointer to a function f returning int whose parameters and int, int.
When we use the name of a function to pass arguments, are we using a pointer to that function?
Example:
int foo(int a, int b);
int main(void)
{
int a = foo(1,3); //foo() it's a pointer to the function foo()?
return 0;
}
The term you're looking for is function designator. It is not a pointer type, but most of the time, it is converted to one.
Quoting the C11 standard, chapter §6.3.2.1, (emphasis mine)
A function designator is an expression that has function type. Except when it is the
operand of the sizeof operator, the _Alignof operator,65) or the unary & operator, a
function designator with type ‘‘function returning type’’ is converted to an expression that has type ‘‘pointer to function returning type’’.
Related, from the "function call" part of the spec, chapter 6.5.2.2
The expression that denotes the called function 92) shall have type pointer to function
returning void or returning a complete object type other than an array type.
which tells us, at the function call, the designator actually gets converted into a pointer.
As much as I go over the C11 standard, I can't see a resolution to the question of whether lvalues are converted to rvalues when they appear as the controlling expression in a _Generic expression. For example, does the following function return 1 or 0?
int func()
{
const int x;
return _Generic( x, int: 1, default: 0 );
}
In the standard, lvalue conversion is defined as follows (6.3.2.1.2):
Except when it is the operand of the sizeof operator, the _Alignof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. If the lvalue has qualified type, the value has the unqualified version of the type of the lvalue; additionally, if the lvalue has atomic type, the value has the non-atomic version of the type of the lvalue; otherwise, the value has the type of the lvalue...
It apparently follows that func returns 1. The controlling expression, 'x', undergoes lvalue conversion as it does not appear in one of the excepted circumstances. Therefore, it has type int and 1 is selected.
On the other hand, the standard says (6.5.1.1.2):
...The type name in a generic association shall specify a complete object type other than a variably modified type...
and (6.3.2.1.3):
Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue...
The only reason to explicitly rule out variably modified types that I can see is to allow for arrays but not for variable length arrays (since the type is already required to be a complete object type). Since it seems clear that lvalue conversion and pointer conversion either both apply or neither applies to _Generic controlling expressions, this suggests that conversion does not take place. Otherwise the exclusion of variably modified types is superfluous and extremely confusing.
This seems to me to justify the argument that lvalue conversion is implicitly only relevant to evaluated statements, and the controlling expression of a _Generic is not evaluated. By this understanding, there is no lvalue conversion, and in the example given 'x' has its unconverted type of const int and so func returns 0.
Is there anything in the standard that clarifies this issue? In particular, would func have the same return value on any complying implementation? Finally, are the popular compilers (e.g., clang, gcc, etc.) consistent on this issue?
I should note that I am using the committee draft of the standard, so if the final version clarifies this then please let me know.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
function call with different semantics
I am reading about function pointers in C. I tried this program:
#include <stdio.h>
int foo(void)
{
printf("At foo.");
return 0;
}
int main (void)
{
printf("%p\t%p\t%p\n", &foo, foo, *foo);
return 0;
}
The output for this program is:
0040138C 0040138C 0040138C
In 1-D array <datatype> <identifier>[N], identifier and &identifier points to the same value but the nature of the values are different. One is of type datatype* and the other is of type pointer to the 1-D array. Analogously, for functions, the foo and &foo are the same. But what about *foo and what is the nature of &foo, foo, *foo?
A plain foo is already a function pointer:
6.3.2.1 - 4
A function designator is an expression that has function type.
Except when it is the operand of the sizeof operator or the unary
& operator, a function designator with type ‘‘function returning
type’’ is converted to an expression that has type ‘‘pointer to
function returning type’’.
You may obtain the address of a function using &, which yields a pointer to function ...:
6.5.3.1 - 1-3
The operand of the unary & operator shall be either a function
designator... The unary & operator yields the address of its operand.
If the operand has type ‘‘type’’,
the result has type ‘‘pointer to type’’
It's legal to apply the indirection operator to a function designator:
6.5.3.2 - 3
The unary * operator denotes indirection. If the operand points to a
function, the result is a function designator
tldr:
So there you have it. They all do the same thing.
EDIT
What is 'function type` in C
Quick! To the standard!
6.2.5 - 1
Types are partitioned into object types (types that describe
objects) and function types (types that describe functions).
6.2.5 - 20
A function type describes a function with specified return type. A
function type is characterized by its return type and the
number and types of its parameters. A function type is said to be
derived from its return type, and if its return type is T, the
function type is sometimes called ‘‘function returning T’’. The
construction of a function type from a return type is called
‘‘function type derivation’’
In C/C++ a function can be used only in 2 ways: you can take its address and you can call it. You cannot do anything else with it.
So, foo is a function itself. C++ has a standard conversion 4.3 Function-to-pointer conversion. This means that foo will be automatically converted to &foo. Notation &&&&foo results in a syntax error.
In C++ 5.3.1.1 Unary operators there is wording that allows dereferencing function pointers with the result of the function itself. This implies that multiple *'s should not be allowed. Nevertheless they work at least in MSVC and GCC. Maybe this is so because compiler applies Function-to-pointer conversion immediately after dereferencing before processing the next operation.
I do not see good reasoning for allowing multiple *'s and not allowing multiple &'s with functions. For some reason different logic is implemented for * and & operations.
You can try to cast foo to char* and dereference this pointer. It will contain bytes of the machine code. The length of these bytes is unknown. Read/write protection of this address is unknown too. Many CPU architectures allow setting execute bit without setting read and write bits. So, you can call the function but an attempt to read at this address may result in a crash.