1
#include <iostream>
using std::cout;
using std::endl;

int a[] = { 10, 20 };

int b[] = { 30, 40 };

int main(int argc, char ** argv)
{
 int * p = a;

 for (int i = 0; i < 4; i++)
 {
  cout << *(p + i) << endl;
 }

 return 0;
}

Why does it work?

vitaut
  • 49,672
  • 25
  • 199
  • 336
mr. Vachovsky
  • 1,128
  • 2
  • 13
  • 23

8 Answers8

4

This is a classic example of undefined behavior. Undefined behaviour doesn't mean crash - it means undefined beaviour - it can work, crash, not work, not crash, and virtually anything else

Community
  • 1
  • 1
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • We are made many tests in Microsoft Visual Studio C++ 2008 , and it is work. – mr. Vachovsky Nov 24 '10 at 08:04
  • @mr. Vavhovsky: Yes, but, first it is not portable, and second, does MSVC, anywhere in the documentation guarantee that two global arrayed defined in turn will have contiguous memory? I doubt that, therefore this is still undefined behaviour. See my link to see the differences between implementation-defined and undefined – Armen Tsirunyan Nov 24 '10 at 08:06
  • @mr. Vachovsky: It jsut complete luck that it works. It may stop work with the next version of the compiler. Somebody else described this before as speeding on highway. It's illegal and if you get caught then you will get put in jail. But the cop is not always there to catch you (thus sometimes it works and sometimes you go to jail). – Martin York Nov 24 '10 at 08:08
  • @mr. Vachovsky: actually it works here, with G++ 4.5.1. Anyway that's just a case Could depend on lots of stuff. – peoro Nov 24 '10 at 08:08
2

C and C++ doesn't do any checking at runtime, about what memory locations you're trying to access. You can access memory cells beyond your array and that is going to work. If in this way you're accessing memory you know about (memory that C++ standard or your compiler tell you how is allocated) anything will work fine (you could even actually do that on purpose) otherwise it's a bug and you'r application will get unpredictable behavior.

In your case it means that a and b are on consecutive memory cells. Anyway this only depends on your compiler. Your code may not work on different compilers, on different versions of your compiler, or on even on your same compiler, if you use other compile options.

peoro
  • 25,562
  • 20
  • 98
  • 150
1

It'll work (sometimes) because the compiler will (sometimes - well, often) put the arrays next to each other in memory. Starting with a pointer to the first position in the first array, you can (Sometimes) traverse both arrays just by incrementing the pointer.

The fact that the memory is laid out in this way is not at all guaranteed and is not something any 'real' program should rely on.

Because the standard does not specify how the compiler should behave in this situation, it is called Undefined Behaviour (UB). Some info here.

Community
  • 1
  • 1
sje397
  • 41,293
  • 8
  • 87
  • 103
0

It works by by chance.

Your code exposes undefined behaviour and, amongst the undefined behaviour, there's also the chance that it may apparently "work".

Simone
  • 11,655
  • 1
  • 30
  • 43
0

My guess is that your output is:

10
20
30
40

Your code relies on undefined behavior: in your case a and b appear to be contiguous in memory, but that is not guaranteed.

When reaching the undefined behavior limit, anything can happen. By anything I mean : it can "work" or it could crash, or it could launch a missile to Cuba.

ereOn
  • 53,676
  • 39
  • 161
  • 238
0

Because the compiler allocate b right a in memory. Try printing the actual address of a, b, and p for every loop iteration and you'll see it pretty nicely. That's what usually happens for variables declared on consecutive lines. But you can't trust this. Compiler optimizations could do something else. If you need confidence that the memory assigned for two variables is contiguous, use a struct.

kichik
  • 33,220
  • 7
  • 94
  • 114
0

It works because your compiler has allocated memory for a and b in a way that b is immediate behind a. This is not reproducible and that's why you have undefined behaviour.

Just insert another variable between a and b, use another compiler, or (my favorite:) rename the variables. I've seen a compiler that arranges the variables in alphabetic order.

Your code 'works' by accident.

harper
  • 13,345
  • 8
  • 56
  • 105
0

This is an undefined behaviour, so it will not work in general. A good example of where it doesn't work is clang. This compiler is smart enough to optimize away b when link-time optimization is enabled.

vitaut
  • 49,672
  • 25
  • 199
  • 336