Reputation: 2297
I cannot figure this out:
int main() {
int (*) (int *) = 5;
return 0;
}
The above assignment compiles with g++ c++11. I know that int (*) (int *)
is a pointer to a function that accepts an (int *)
as argument and returns an int, but I do not understand how you could equate it to 5. At first I thought it is a function that constantly returns 5 (from my recent learning in F#, probably, haha), then I thought, briefly, that the function pointer points to memory location 5, but that does not work, clearly, and neither does hex values.
Thinking that it could be because the function returns an int, and that assigning an int is ok (somehow), I also tried this:
int * (*) (int *) = my_ptr
where my_ptr
is of type int *
, the same type as this second function pointer, as in the first case with type int. This does not compile. Assigning 5, or any int value, instead of my_ptr
, doesn't compile for this function pointer either.
So what does the assignment mean?
Update 1
We have confirmation that it is a bug, as shown in the best answer. However, it is still not known what actually happens to the value that you assign to the function pointer, or what happens with the assignment. Any (good) explanations on that would be very much appreciated! Please refer to the edits below for more clarity on the problem.
Edit 1
I am using gcc version 4.8.2 (in Ubuntu 4.8.2)
Edit 2
Actually, equating it to anything works on my compiler. Even equating it to a std::string variable, or a function name that returns a double, works.
Edit 2.1
Interestingly, making it a function pointer to any function that returns a data type that is not a pointer, will let it compile, such as
std::string (*) () = 5.6;
But as soon as the function pointer is to a function that returns some pointer, it does not compile, such as with
some_data_type ** (*) () = any_value;
Upvotes: 88
Views: 12529
Reputation: 2327
As other answers have pointed out, it is a bug that
int (*) (int *) = 5;
compiles. A reasonable approximation of this statement that would be expected to have a meaning is:
int (*proc)(int*) = (int (*)(int*))(5);
Now proc
is a pointer-to-function that expects the address 5
to be the base address of a function that takes an int*
and returns an int
.
On some microcontrollers/microprocessors 5
might be a valid code address, and it might be possible to locate such a function there.
On most general-purpose computers, the first page of memory (addresses 0-1023
for 4K pages) are purposely invalid (unmapped) in order to catch null
pointer accesses.
Thus, while behavior depends on the platform, one can reasonably expect a page fault to occur when *proc
is invoked (e.g., (*proc)(&v)
). Before the time at which *proc
is invoked, nothing unusual happens.
Unless you are writing a dynamic linker, you almost certainly shouldn't be numerically calculating addresses and assigning them to pointer-to-function variables.
Upvotes: 9
Reputation: 145899
It's a bug in g++.
int (*) (int *)
is a type name.
In C++ you cannot have a declaration with a type name without an identifier.
So this compiles with g++.
int (*) (int *) = 5;
and this compiles as well:
int (*) (int *);
but they are both invalid declarations.
EDIT:
T.C. mentions in the comments bugzilla bug 60680 with a similar test case but it has not yet been approved. The bug is confirmed in bugzilla.
EDIT2:
When the two declarations above are at file scope g++ correctly issues a diagnostic (it fails to issue the diagnostic at block scope).
EDIT3:
I checked and I can reproduce the issue on the latest release of g++ version 4 (4.9.2), latest pre-release version 5 (5.0.1 20150412) and latest experimental version 6 (6.0.0 20150412).
Upvotes: 60
Reputation: 7100
It is not valid C++. Remember that because your particular compiler happens to compile it doesn't make it valid. Compilers, like all complex software, sometimes have bugs and this appears to be one.
By contrast clang++
complains:
funnycast.cpp:3:11: error: expected expression
int (*) (int *) = 5;
^
funnycast.cpp:3:18: error: expected '(' for function-style cast or type construction
int (*) (int *) = 5;
~~~ ^
funnycast.cpp:3:19: error: expected expression
int (*) (int *) = 5;
^
3 errors generated.
This is the expected behavior because the offending line is not valid C++. It purports to be an assignment (because of the =
) but contains no identifier.
Upvotes: 28
Reputation: 41686
/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/cc1plus.exe -da so.cpp
This command line generates a lot of intermediate files. The first of them, so.cpp.170r.expand
, says:
...
int main() ()
{
int D.2229;
int _1;
;; basic block 2, loop depth 0
;; pred: ENTRY
_1 = 0;
;; succ: 3
;; basic block 3, loop depth 0
;; pred: 2
<L0>:
return _1;
;; succ: EXIT
}
...
This still doesn’t answer what happens exactly, but it should be a step in the right direction.
Upvotes: 2