-3

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.

kmario23
  • 57,311
  • 13
  • 161
  • 150

1 Answers1

6

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.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
JeJo
  • 30,635
  • 6
  • 49
  • 88
  • 1
    @kmario23 Just for example, see this(https://www.ideone.com/TScRGs) and this( https://www.ideone.com/xqcsAI) two outputs of your codes. Now you have for both, same outcomes. How? that's the magic of UB. You can not define it properly. The only solution is adopt good coding standards(https://stackoverflow.com/questions/3016077/how-to-spot-undefined-behavior) – JeJo Jun 08 '18 at 23:08