Как правильно разыменовать указатель массива typedef?

Я использую сторонний код, тип которого определен как:

typedef float MarkerData[3];  

позже в коде у меня есть массив данных о положении этого маркера, на который ссылаются как:

MarkerData* Markers;    

Я использую этот код для итерации этого массива:

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

MarkerData* mData = (Markers + s);

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


}

Код не падает, но значения с плавающей запятой смешиваются. Из отладки я вижу, что я правильно получаю значение markerPosition.X на каждой итерации, но Z и Y берутся из другого массива. Я предполагаю, что я использую здесь неправильную арифметику указателя, но, несмотря ни на что, не могу этого понять. Этот typedef действительно новый для меня, и я не знаю, что может быть не так?


person user2426290    schedule 15.06.2017    source источник
comment
int32 s = 0; должно быть size_t s = 0;   -  person πάντα ῥεῖ    schedule 15.06.2017
comment
@ πάνταῥεῖ Это спорно и может зависеть от типа totalMarkers.   -  person François Andrieux    schedule 15.06.2017
comment
тип totalMarkers - int32   -  person user2426290    schedule 15.06.2017
comment
Не могли бы вы предоставить минимальный воспроизводимый пример вместе со сравнением полученных результатов и ожидаемых результатов? Трудно окончательно понять, что вы сделали не так, имея такую ​​маленькую информацию.   -  person François Andrieux    schedule 15.06.2017
comment
Понятно, если этого объяснения недостаточно, я представлю пример MCV.   -  person user2426290    schedule 15.06.2017
comment
У меня есть сильное подозрение, что вы хотели, чтобы формат *(mData)[0] был (*mData)[0]. И не сбой никогда не следует приравнивать к правильному. Выполнение этого через Valgrind скорее всего пометит нарушения чтения.   -  person WhozCraig    schedule 15.06.2017
comment
Скобки в (mData) ничего не делают. *(abc)[splat] означает то же самое, что и *abc[splat]. Скобки должны заключать два или более маркера синтаксиса, чтобы фактически выполнять группировку, тем самым влияя на анализ синтаксиса. Исключением может быть что-то вроде #define mData badly + behaved, где автор макроса забыл круглые скобки, поэтому они нужны вызывающей стороне.   -  person Kaz    schedule 15.06.2017


Ответы (1)


Эта ошибка вызвана неправильным пониманием приоритета оператора. Операторы имеют порядок, в котором они применяются. Это похоже на приоритет операций в математике, где, например, умножение имеет более высокий приоритет, чем сложение. operator* (оператор разыменования) имеет более низкий приоритет, чем operator[] (оператор нижнего индекса). Это означает, что выражение *(mData)[2] анализируется как "разыменование третьего элемента по указателю mData". Третий элемент предположительно представляет собой массив из 3 чисел с плавающей запятой (если вы не вышли за пределы массива, на который указывает mData). Затем вы разыменовываете полученный массив. Разыменование массива дает вам первый элемент в этом массиве. По сути, вы снова и снова выбираете первый элемент разных маркеров. Вы можете изменить приоритет, используя круглые скобки. Вместо этого попробуйте (*mData)[0]. Это сначала заставит разыменовать ваш указатель, предоставив вам массив floats, к которому затем будет осуществляться доступ по индексу с оператором нижнего индекса.

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

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

Большинства ваших проблем можно было бы избежать, используя правильные контейнеры C++, такие как std::array и std::vector.

person François Andrieux    schedule 15.06.2017
comment
Нет, недоразумение заключается не только в приоритете табу. Существует неправильное понимание того, что скобки в (mData) делают что-то отличное от mData (в обычном случае, когда mData не является макросом с плохим поведением). - person Kaz; 15.06.2017