Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the C++ linker allow undefined functions?

This C++ code, perhaps surprisingly, prints out 1.

#include <iostream>  std::string x();  int main() {      std::cout << "x: " << x << std::endl;     return 0; } 

x is a function prototype, which seems to be viewed as a function pointer, and C++ Standard section 4.12 Boolean conversions says:

4.12 Boolean conversions [conv.bool] 1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. For direct-initialization (8.5), a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.

However, x is never bound to a function. As I would expect, the C linker doesn't allow this. However in C++ this isn't a problem at all. Can anyone explain this behavior?

like image 500
chmullig Avatar asked Nov 25 '14 20:11

chmullig


People also ask

How do you fix undefined reference to function in C?

Used the GCC compiler to compile the exp. c file. The error: undefined reference to function show() has appeared on the terminal shell as predicted. To solve this error, simply open the file and make the name of a function the same in its function definition and function call.

What does undefined reference in C mean?

An “Undefined Reference” error occurs when we have a reference to object name (class, function, variable, etc.) in our program and the linker cannot find its definition when it tries to search for it in all the linked object files and libraries.

How do you fix a undefined reference in C++?

You can fix undefined reference in C++ by investigating the linker error messages and then providing the missing definition for the given symbols. Note that not all linker errors are undefined references, and the same programmer error does not cause all undefined reference errors.


1 Answers

What's happening here is that the function pointer is implicitly converted to bool. This is specified by [conv.bool]:

A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true

where "null pointer value" includes null function pointers. Since the function pointer obtained from decay of a function name cannot be null, this gives true. You can see this by including << std::boolalpha in the output command.

The following does cause a link error in g++: (int)x;


Regarding whether this behaviour is permitted or not, C++14 [basic.odr.ref]/3 says:

A function whose name appears as a potentially-evaluated expression is odr-used if it is the unique lookup result or the selected member of a set of overloaded functions [...]

which does cover this case, since x in the output expression is looked up to the declaration of x above and that is the unique result. Then in /4 we have:

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

so the program is ill-formed but no diagnostic is required, meaning that the program's behaviour is completely undefined.

Incidentally this clause implies that no link error is required for x(); either, however from a quality-of-implementation angle; that would be silly. The course that g++ has chosen here seems reasonable to me.

like image 115
M.M Avatar answered Sep 28 '22 02:09

M.M