Search code examples
c++c++11tostringstdstringstdarray

Strange outputs of std::to_string in C++11


I have this small snippet of C++ code:

#include <array>
#include <string>
#include <iostream>

int main() 
{
  std::string name = "mario";
  std::cerr << "Hello world! " + name + "\n";

  std::array<float, 4> arr = {12, 12.3, 13, 14};
  std::cerr << "first item is: " + std::to_string(arr.front()) << std::endl;
  std::cerr << "last item is: " + std::to_string(arr[-1]) << std::endl;
  return 0;
}

It compiles and outputs the following:

work ❯ c++ -std=c++11 -o hello_world hello.cpp
work ❯ ./hello_world
Hello world! mario
first item is: 12.000000
last item is: 0.000000

But, if I comment out the first two lines like:

#include <array>
#include <string>
#include <iostream>

int main() 
{
  //std::string name = "mario";
  //std::cerr << "Hello world! " + name + "\n";

  std::array<float, 4> arr = {12, 12.3, 13, 14};
  std::cerr << "first item is: " + std::to_string(arr.front()) << std::endl;
  std::cerr << "last item is: " + std::to_string(arr[-1]) << std::endl;
  return 0;
}

And compile and run it. Then it outputs the following:

work ❯ c++ -std=c++11 -o hello_world hello.cpp
work ❯ ./hello_world
first item is: 12.000000
last item is: 12.000000

I have three questions:

  1. why do we get 0.000 in the first case, when using arr[-1]?
  2. why do we get 12.000 in the second case when using arr[-1]?
  3. why do we get different output for arr[-1] in the second case, when we comment out first two statements?

Edit: Based on comments, I understand that arr[-1] would be undefined behavior and hence returns 0.000 in the first case. But, how does commenting out the other statements change this behavior? This is completely confusing to me since I come from Python world.


Solution

  • This is because of Undefined behavior, as std::array::operator[] does not perform any bounds checking, and you are accessing something that is not there.

    std::array::operator[] Returns a reference to the element at specified location pos. No bounds checking is performed.

    Therefore, no matter what you change or comment, the UB will still be UB.