array1[array2[1]] question

Pages: 12
In JAVA, the language I program in normally, array1[array2[1]] means that you take cell 1 out of array2 and use that number to access the relevant cell in array1.

I am now porting some C++ code to JAVA, and base don the code, it seems to mean that I it provides access to cell 1 of array1? Is that correct?

It should be the same as in Java.
Well, it is not. Because this is the more expansive version:

First they define this struct:

typedef struct
{
int n;
double *x, *y;
}
curve_type;

This object is passed on to a function as an array of 9 here:

int fitmodel(curve_type *model)

In the function, the following array is defined
int p1[9] = {-1, -1, -1, -1, 3, -1, 2, 3, 0};

This function calls a second function with

findsegment(model[p1[k]]);

findsegment then uses model[k] for the calculations, never model[-1].

So, something is different. Because in JAVA, you would not get to curve_type number nine.



Can you try to come up with a short, complete example with two arrays that works that way? I suspect there is probably something else going on that's causing the problem, as it should work as Java does.
1
2
3
4
5
6
typedef struct
{
int n;
double *x, *y;
}
curve_type;
This smells more like C and less like C++.

findsegment then uses model[k] for the calculations, never model[-1].

You realise that -1 is out of bounds? You're accessing random memory that is who knows what! C++ does not have bounds checking like Java ;p and it can't, or it would cause a lot of perfectly OK code to throw ArrayIndexOutOfBoundsErrors
Last edited on
Yes, I am perfectly aware of the -1 issue. That is why I know something different is going on, because in JAVA, it will throw a ArrayIndexOutOfBoundsError.

Anyway, the code in more expansive example extracted from the source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
typedef struct
{
int n;
double *x, *y;
}
curve_type;

main(argc, argv)
int argc;
char *argv[];
{
   curve_type model[10];
   int[][] imageData;
   readmodel(modelfile, model);
   readData(imageFile, imageData);
   fitmodel(imageData, model);
}

fitmodel(int imageData, curve_type *model)
{
   int p0[9] = {-1,  0,  0,  0, 0,  0, 1, 2, 1};
   int p1[9] = {-1, -1, -1, -1, 3, -1, 2, 3, 0};
   findsegment(model[p1[k]]);
}

int findsegment(curve_type curve)
{
   int np;
   double *xp, *yp;

   np = curve.n;
   xp = curve.x;
   yp = curve.y;
   for(int i=1; i<np-1; i++)
   {
      x1 = xp[i-1];
      y1 = yp[i-1];
      x2 = xp[i];
      y2 = yp[i];
      x3 = xp[i+1];
      y3 = yp[i+1];
      and further....
   }
}

So yes, it passes p1[k] to the model array, and it uses k by itself to reference to the object in the model array itself.

Edit: Yes, the source code is a mix of C, C# and C++.
Last edited on
So yes, it passes p1[k] to the model array, and it uses k by itself to reference to the object in the model array itself.


How are you determining that?

I agree with LB here. If -1 is the index being used for model, you will be accessing bad memory which might go completely unnoticed by your program. Nothing in your pasted code checks for that situation.

I see no reason why k would be used as the index here. I suspect you are jumping to the wrong conclusion.
Last edited on
Sorry, the program complied with this code works fine. So, how does it resolve the -1 problem as it obviously does not have that problem.
closed account (1vRz3TCk)
C++ does not stop you doing stupid things like using a negative index in an array. You will need to check the value is not negative yourself before using it.
Accessing an element of an array simply accesses the desired block of memory. If you try to access an out of bounds index, you will access whatever memory surrounds the array. This might be other variables, or it might be inaccessible, or it might be unused. What actually happens is unreliable and mostly unpredictable.

What you can try to do to illustrate this, is to put some variables on the stack and see how it responds:

1
2
3
4
5
6
7
8
9
int main()
{
  int A = 5;
  int ar[2] = {0,0};
  int B = 10;

  cout << ar[-1];  // might print '5', the contents of A, since A is before ar[] in memory
  cout << ar[2];  // might print '10', the contents of B
}


but again note that I said "MIGHT". There's no guarantee it will work that way.

In any event, you should never try to use a negative index on an array. In your case you will need to check the index first to see if it's negative, before actually using it. Something like this:

1
2
3
4
5
6
7
8
9
index = p0[k];
if(index < 0)
{
  // give error, do not proceed with operation
}
else
{
  findsegment(model[index]);
}
Well, the output generated is for the 10 curves in the model array, so, something goes right there despite being referenced as model[p1[k]]. No runtime errors, no arrayoutofbound exceptions.
In C++, these two code snippets are exactly the same:
1
2
int Array[] = /*something*/;
cout << Array[i] << *(Array+i) << endl;
1
2
int *Array = /*something*/;
cout << Array[i] << *(Array+i) << endl;
Additionally, both Array[i] and *(Array+i) are the same. If i is negative, then you know what happens...

Kim van der Linde wrote:
No runtime errors, no arrayoutofbound exceptions.
C++ DOES NOT THROW ARRAY INDEX OUT OF BOUNDS ERRORS IF YOUR ARRAY INDEX IS OUT OF BOUNDS. There is NO safety involved, your code will access whatever memory you tell it to unless you get a segmentation fault.

Try this code:
1
2
3
int A1[] = {2, 3};
int A2[] = {1, 2, 3, 4, 5};
cout << A2[A1[1]] << endl;
The output should be 4. If it is not 4, either I did my math in my head wrong five times in a row, or your compiler is stupid ;)

Also, read Disch's post.
Last edited on
I am a JAVA programmer who is trying to understand existing C#/C++ code that has to above issue. The program works flawlessly for many many years now, so I do not think it accesses an negative reference. What it does do is use model[0], then model[1], etc till it reaches the end as if k is used as a reference, and not p1[k].
I do not have C compiler, I program JAVA. Last time we changed the C code, someone else helped me.
Not here ;p it's definitely doing everything except to "use model[0], then model[1], etc".
Okay, so now you know why I am puzzled. Looks like you guys are as well....

And I do not need to get the C code to work, so no help needed. Only trying to understand the original code.
Last edited on
If you have a pointer you could make so that indexing -1 is valid but that stupid.
1
2
const char* p = ("ABC" + 1);
cout << p[-1] << endl; // This will print "A" 
You must be misreading or misinterpretting the code.


Also, I just noticed this....

1
2
3
4
main(argc, argv)
int argc;
char *argv[];
{


Old-style C argument lists? Didn't they stop supporting this in like 1990? Just how old is this code and how does it even still compile?
So what's the question now? You want to throw an IndexOutOfBoundsException when using an invalid index or what?
Yes, the code is from 1995-1996 and a mix of C/C#/C++, and we recompiled it in 2006 with a few small changes (hardcoded directory addresses). The question is: What gets passed on in the above example to the findsegment function. For k = 3, is that model[3] or model[-1]? The program spits out model[3], but everybody and anything says it should be model[-1].

Last edited on
Pages: 12