0

I am using 3rd party code, which has type defined as:

typedef float MarkerData[3];  

later in the code, I have array of this marker position data referenced as:

MarkerData* Markers;    

I am using this code to iterate this array:

for (int32 s = 0; s < totalMarkers; s++)
{

MarkerData* mData = (Markers + s);

markerPosition.X = *(mData)[0];
markerPosition.Y = *(mData)[1];
markerPosition.Z = *(mData)[2];


}

The code does not crash, but float values get mixed. From debug I can see, that I properly get markerPosition.X value on every iteration, but Z and Y are taken from other array. I suppose I am using wrong pointer arithmetic here, but no matter what, can not figure it out. This typedef really is new to me, and I don't know - what might be off?

user2426290
  • 382
  • 2
  • 14
  • `int32 s = 0;` should be `size_t s = 0;` – πάντα ῥεῖ Jun 15 '17 at 19:22
  • @πάνταῥεῖ That's debatable and may depends on the type of `totalMarkers`. – François Andrieux Jun 15 '17 at 19:23
  • totalMarkers type is int32 – user2426290 Jun 15 '17 at 19:24
  • 1
    Can you please provice a [MCVE] along with a comparison between the results you obtained and the results you expected? It's hard to definitively know what you did wrong with such little information. – François Andrieux Jun 15 '17 at 19:24
  • Understood, if that explanation is not enough, I will submit MCV example – user2426290 Jun 15 '17 at 19:25
  • 1
    I have a *strong* suspicion that you intended your format of `*(mData)[0]` to be `(*mData)[0]`. And "does not crash" should never be equated with "is correct". Running this through Valgrind would *likely* flag read-violations. – WhozCraig Jun 15 '17 at 19:29
  • The parentheses on `(mData)` **do not do anything**. `*(abc)[splat]` means exactly the same thing as `*abc[splat]`. Parentheses have to enclose two or more tokens of syntax in order to actually perform *grouping*, thereby influencing the parse of the syntax. The exception would be something like `#define mData badly + behaved`, where the macro writer forgot parentheses, so the caller needs them. – Kaz Jun 15 '17 at 19:43

1 Answers1

3

This is a bug caused by a misunderstanding of Operator Precedence. Operators have an order in which they are applied. This is similar to operator precedence in mathematics where, for example, multiplication has a higher priority than addition. operator* (dereferencing operator) has lower precedence than operator[] (subscript operator). What this means is the expression *(mData)[2] is parsed as "dereference the third element at pointer mData". The third element is presumably an array of 3 floats (if you haven't exceeded the bounds of the array pointed to by mData). You then dereference that resulting array. Dereferencing an array gives you the first element in that array. In essence you are fetching the first element of different markers over and over again. You can alter precedence using parentheses. Try (*mData)[0] instead. This will force the dereferencing of your pointer first, giving you the array of floats which is then accessed by index with the subscript operator.

for (int32 s = 0; s < totalMarkers; s++)
{
    MarkerData* mData = (Markers + s);

    markerPosition.X = (*mData)[0];
    markerPosition.Y = (*mData)[1];
    markerPosition.Z = (*mData)[2];
}

Most of your troubles could have been avoided with the use of proper c++ containers such as std::array and std::vector.

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
  • No, the misunderstanding is not just tabout precedence. There is the misundertsanding that the parentheses in `(mData)` do anything different from just `mData` (in the ordinary case, when `mData` isn't a badly behaving macro). – Kaz Jun 15 '17 at 19:41