tags:

views:

75

answers:

2

Let's say I have an array like this:

string x[2][55];

If I want to fill it with "-1", is this the correct way:

fill(&x[0][0],&x[2][55],"-1");

That crashed when I tried to run it. If I change x[2][55] to x[1][54] it works but it doesn't init the last element of the array.

Here's an example to prove my point:

  string x[2][55]; 
  x[1][54] = "x";
  fill(&x[0][0],&x[1][54],"-1");
  cout<<x[1][54]<<endl; // this print's "x"
+3  A: 

Because when you have a multi-dimensional array, the address beyond the first element is a little confusing to calculate. The simple answer is you do this:

&x[1][55]

Let's consider what a 2d array x[N][M] is laid out in memory

[0][0] [0][1] ... [0][M-1] [1][0] [1][1] ... [1][M-1] [N-1][0] .. [N-1][M-1]

So, the very last element is [N-1][M-1] and the first element beyond is [N-1][M]. If you take the address of [N][M] then you go very far past the end and you overwrite lots of memory.

Another way to calculate the first address beyond the end is to use sizeof.

&x[0][0] + sizeof(x) / sizeof(std::string);
R Samuel Klatchko
Aaaah, and fill fills the interval [first, last) - closed at first, open at last, so "last" itself is just beyond the last filled element. I see.
Chris
A: 

From the formal and pedantic point of view, this is illegal. Reinterpreting a 2D array as a 1D array results in undefined behavior, since you are literally attempting to access 1D x[0] array beyond its boundary.

In practice, this will work (although some code analysis tools might catch an report this as a violation). But in order to specify the pointer to the "element beyond the last" correctly, you have to be careful. It can be specified as &x[1][55] or as &x[2][0] (both are the same address).

AndreyT
@AndreyT - are you sure about that? I read C++03 spec 8.3.4.7, .8 and .9 as requiring a multi-dimensional array to be put in memory consecutively in row order.
R Samuel Klatchko
@R Samuel Klatchko: It has been debated many times. Yes, it is required to be put in memory that way. Yet, the pointer arithmetic rules clearly state that if you have a pointer of type `string *` that points to an element of 1D array `x[0]`, then you are not allowed to cross the boundary of 1D array `x[0]` with pointer arithmetic. If a compiler chooses to enforce that by using "compiler magic", it is fully authorized to do so.
AndreyT
I consider multidimensional arrays in C and C++ to be broken beyond all hope of repair.
Omnifarious