1

I am learning C++ on a linux machine. I just tried “int i();” to declare a function but I forgot to define it. But to my surprise, this code can be compiled and output 1. I feel very confused. I tried “int I{};”, it still compiled with no errors. Please help to explain. Thanks in advance.

 //test1.cpp
#include <iostream>
int main(void)
{
    int i{};
    std::cout << i << std::endl;
    return 0;
}

g++ test1.cpp
./a.out
Output is: 0

//test2.cpp
#include <iostream>
int main(void)
{
    int i();
    std::cout << i << std::endl;
    return 0;
}

g++ test2.cpp
./a.out
Output is : 1
Wu Xiliang
  • 316
  • 3
  • 10
  • 2
    if you don't call that function anywhere in the code, that's fine. otherwise, you will receive an error on linking since the linker would not be able to find the function definition – mangusta Nov 13 '18 at 02:44
  • Thank you for your quick response. What about the output? Why the output is 1? And the “int i{};”. What does it mean? – Wu Xiliang Nov 13 '18 at 02:47
  • 1
    See https://stackoverflow.com/questions/52478974/printing-time-function-to-console-produces-1 – Raymond Chen Nov 13 '18 at 02:52
  • @RaymondChen Thanks for the recommended article. What about “int i {};” What does this syntax do? – Wu Xiliang Nov 13 '18 at 03:05
  • 1
    https://stackoverflow.com/questions/24953658/what-are-the-differences-between-c-like-constructor-and-uniform-initialization – Raymond Chen Nov 13 '18 at 04:06

2 Answers2

3

In your first example, you define a variable named i, and value-initialise it, which for int means zero-initialisation.

int i{}; // defines i, initialised to zero

In your second example, you declare a function named i, which takes no parameters, and return int:

int i(); // declares a function

When you print this:

std::cout << i << std::endl;

i first get converted to bool (i decays to a function non-nullptr pointer, then it becomes true), and then printed as an integer, that's why you get 1. The compiler can make this conversion without the definition of i (as the result is always true), that's why you got no linker error.

If your intent was to call this function, and print the result, you'll need to use i():

std::cout << i() << std::endl;

This, of course, needs i's definition.

geza
  • 28,403
  • 6
  • 61
  • 135
1

In your code:

//test1.cpp
#include <iostream>
int main(void)
{
    int i{};
    std::cout << i << std::endl;
    return 0;
}

You are not actually declaring a function without defining it. The line of code int i{}; within the main() function here is a variable of type int named i and you are using a brace initializer list to initialize the variable i with out any values and in most cases could be 0 but can vary by compiler.

//test2.cpp
#include <iostream>
int main(void)
{
    int i();
    std::cout << i << std::endl;
    return 0;
}

In this situation it is basically the same thing. You are within main() and by the rules of the language "you can not declare-define a function within a function", so this results in a declaration - definition of a variable. The only difference here is you are not using a brace initializer list here you are using it's ctor constructor called value initialization. Again you are not passing any values to it and in your case it's assigning an arbitrary value of 1.

Now if your code looked like this:

#include <iostream>

int i();

int main() {
     std::cout << i() << '\n';
     return 0;
}

This would fail to compile because the function i is declared but not defined. However if you did this:

#include <iostream>

// The text in quotes is not meant to be a string literal. It
// is the message of the text that represents any integer X.
int i() { return /*"some int value"*/ 1; }

int main() {
    std::cout << i() << '\n';
    return 0;
}

This would compile and run perfectly fine because the function i is both declared and defined.

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • 1
    Why did you opt for `return "some int value"` instead of an actual int value? Saying that it will compile fine is misleading, as converting a string literal to an integer ought to produce a warning at the very least. – paddy Nov 13 '18 at 03:17
  • "in most cases would be 0 but could vary by compiler." It may not vary by compiler. It is [required to initialize to zero](https://en.cppreference.com/w/cpp/language/value_initialization). – Raymond Chen Nov 13 '18 at 04:11
  • @paddy I wasn't referring to a string literal. I was using string text to represent any integer value; READ THE TEXT! I'll update it anyways. – Francis Cugler Nov 13 '18 at 04:24
  • You cannot define a local function, you can declare one. `int i()` declares a function called `i` taking nothing and returning and `int`. If it didn't it would print 0 like the first example instead of 1. – NathanOliver Nov 13 '18 at 04:39
  • 1
    Also, `T()` is called value initialization and will give you a zero initialized object if it does not have a default constructor. – NathanOliver Nov 13 '18 at 04:43
  • @NathanOliver You have both a declaration and a definition and in some cases the declaration and definition can be the same. If you define a function prototype that is its declaration. Then when you implement the function itself somewhere else in the source, that is the definition to the already existing declaration - prototype. Try defining two functions in the same translation unit and scope that has the exact same signature, your code will compile, but it will fail to build at link time because it found multiple definitions of the symbol representation of that function. – Francis Cugler Nov 13 '18 at 06:30
  • 1
    @francis, if the op can't do it, why does it compile? Answer: you can declare a function (a function definition has a body) and printing a function name converts the address to a bool and prints 1. – NathanOliver Nov 13 '18 at 15:58
  • @NathanOliver True, but in the OPs code he never declared a function! It was within main and there for is a variable declaration! – Francis Cugler Nov 13 '18 at 18:10
  • @francis you **can** declare a function a main. You can declare a function in an scope. There are only limitations on where you can define them. – NathanOliver Nov 13 '18 at 20:54
  • No matter the scope `type name();` is always a function declaration. – NathanOliver Nov 13 '18 at 20:55
  • @NathanOliver Not when it is inside of the body of another function. You can not declare a function within a function in C++. See this Q/A https://stackoverflow.com/a/4324780/1757805 – Francis Cugler Nov 14 '18 at 01:48
  • That is about defining a function. Not a declaration. See https://stackoverflow.com/a/28470630/4342498 – NathanOliver Nov 14 '18 at 07:15
  • You might also want to Google the most vexing parse for more about this. – NathanOliver Nov 14 '18 at 07:16