-2

Define an array which has 2 elements

char a[2];

Then assign values and print the 4th elements.

a[0]='a';
a[1]='b';
a[2]='c';
a[3]='d';
cout<<a[3]<<endl;

Why I can get the answer 'd' rather than a run time error? What the value 2 stand for inside [] when declaring the array a? If 2 makes no sense here, why I can't write it as:

char a[];
Jeffrey Bosboom
  • 13,313
  • 16
  • 79
  • 92
SimaGuanxing
  • 673
  • 2
  • 10
  • 29
  • With the code: char a[2] ={'a','b'}; I can only assign two elements that means 2 works here. – SimaGuanxing Jan 24 '15 at 01:16
  • possible duplicate of [Array index out of bound in C](http://stackoverflow.com/questions/671703/array-index-out-of-bound-in-c) – Barmar Jan 24 '15 at 01:19

1 Answers1

2

The indexing operator a[b] in C and C++ can be considered defined as *(&a + sizeof(TA) * b), (interestingly, a[b] and b[a] are also equivalent, but that's another explanation).

Let's walk through the code:

char a[2]; // statically-allocates 2 bytes on the stack, e.g. at `0xFFFF`, and `0xFFFE` (as the stack grows downwards)
a[0] = 'a'; // sets `0xFFFF`
a[1] = 'b'; // sets `0xFFFE`
a[2] = 'c'; // sets `0xFFFD` <-- danger!

Here lies the danger: C/C++ does not mandate that array code have bounds-checking, so your code can be considered equivalent to this:

char a0; // 0xFFFF
char a1; // 0xFFFE
*0xFFFF = 'a';
*0xFFFE = 'b';
*0xFFFD = 'c'; <-- danger! writing to unallocated memory
*0xFFFC = 'd'; <-- uncharted territory! here be dragons!

Your code "works" because 0xFFFD will be memory that exists for two reasons: 1: The stack grows downward and will be reserved by the OS automatically so you won't segfault ("access violation" on Windows), and 2: you aren't coming close to a stack overflow error condition.

However if you were to add more local variables to your function then you'll see that a[2] will overrwrite those values, you also run the risk of overwriting the current stack frame's return address thus corrupting your stack and rendering your program in an indeterminate state that should be terminated immediately).

Consider:

char[2] a;
int     b = 0;
int     c = 0;

a[2] = 'a';

assert( b == 0 ); // this assertion will fail (at least on systems that don't word-align locals)
Dai
  • 141,631
  • 28
  • 261
  • 374
  • `a[b]` is defined as `*(a+b)`, not `*(&a + sizeof(TA) * b)` . You're forgetting that pointer arithmetic means to increment by the size of the object being pointed to. – M.M Jan 24 '15 at 01:30
  • @MattMcNabb yup, I qualified it as "considered as", I just wanted to be clear in case the reader doesn't know that `+` is effectively overridden for pointers. – Dai Jan 24 '15 at 01:32
  • `&a` has type `char (*)[2]`, so `&a + b` is a pointer that points past the end of `a`. (Assuming that by "TA" you meant `char` here). The code you're looking for is `(char *)a + (sizeof(*a) * b)` although it seems to me that it is confusing to use `+` with a pointer to try and be a simpler explanation of what `+` with a pointer does ! Also, `+` is not really "overridden" as the case of using `+` with two integers is completely separate from using it with a pointer and an integer. – M.M Jan 24 '15 at 01:38
  • @Dai I am sorry but I still have one thing don't understand. If I want to define a N element array, but N is based on a known string's length. The code can be: string a = "hello"; int const len = a.length(); int b[len]; The compiler will give error. How can I realize that? Thank you! – SimaGuanxing Jan 24 '15 at 01:46
  • @JoeWang `N` must be known at compile-time. `.length()` is a runtime function, the compiler does not know what `len` is when it builds the program, hence the error. – Dai Jan 24 '15 at 01:53
  • @Dai Thank you. Is that possible to define a array that has an unknown size in C++? I know some functions in STL such as vector can do it but I just want to know whether I can realize it without using STL. This question makes me painful since sometimes I need to copy some specific characters to a char array one by one, but I don't know how to do it since I don't know how many characters I will copy. – SimaGuanxing Jan 24 '15 at 02:10
  • @JoeWang yes, but the array is allocated on the heap, not the stack. Use the `new[]` operator: `char* array = new char[ someLengthVariable ];`, if you have any further questions please move them to a new SO Question posting. – Dai Jan 24 '15 at 02:49