LINUX.ORG.RU

РЕШЕНО. Указатели и приведения типов

 


0

4

Всем привет!

Вопрос по C++. Приведение типов вида (T*)val объявлено устаревшим. Для корректного приведения используется "..._cast". В случае c указателями работает reinterpret_cast<T*>(val) . Но в качественном исходном коде фрагментов с приведением типов (особенно reinterpret_cast) должно быть по возможности меньше. Как правильно передать данные для последнего атрибута в вызове функции glVertexAttribPointer из API OpenGL, который должен быть указателем? Из примера:

int offset = 5 * sizeof(float);

//1. работает / устаревший функционал
glVertexAttribPointer(attrib_idx, 3, GL_FLOAT, false, stride, (int*)offset);

//2. работает / плохой код
glVertexAttribPointer(attrib_idx, 3, GL_FLOAT, false, stride, reinterpret_cast<int*>(offset));

//3. НЕ РАБОТАЕТ
int * ptr_offset = &offset;
glVertexAttribPointer(attrib_idx, 3, GL_FLOAT, false, stride, ptr_offset);

Где в третьем варианте ошибка, как корректно сформировать значение для последнего параметра без приведения типа?

ОТВЕТ: без использования функции приведения типов reinterpret_cast (в явном или скрытом виде) не работает - связано в особенностями реализации API OpenGL.



Последнее исправление: bigov (всего исправлений: 3)

Не понятно, почему работает первые два, ибо ошибки то не будет, но именно работать и не должно, а третий не работает потому что GLvoid * не void *, следовательно без приведения типов не обойтись.

vodz ★★★★★
()
Ответ на: комментарий от vodz

в том-то и затык. Сам сломал мозг. Проверял и void* и int* - все корректно отрабатывает без прямого приведения в GLvoid*.

bigov
() автор топика
Ответ на: комментарий от bigov

Чего тут мозг ломать, void * - стандартное средство для автоматического приведения, а всё остальное в отличии от C в С++ приведения — требует. Почему вы приводите к (int *) — вот где мозг надо ломать, ибо надо к GLvoid *

vodz ★★★★★
()
Ответ на: комментарий от bigov

для переменной типа int

В GLvoid * вам придётс приводить. Но и это не всё. Вы же указываете GL_FLOAT, GLenum type и void * тут специально применяется для того, чтобы можно было указать тип массива. Следовательно offset должет быть не int, а float.

vodz ★★★★★
()
Ответ на: комментарий от bigov

Обычно правильно делать как в варианте 3, но опенгл упоротое апи, и указатель на самом деле не указатель, а смещение, так что делай reinterpret_cast<GLVoid*>

deadNightTiger ★★★★★
()
Ответ на: комментарий от vodz

GL_FLOAT это тип элементов массива, это отражается в sizeof(float) при вычислении offset. Ему надо передать смещение в байтах, которое почему-то имеет тип GLvoid*

deadNightTiger ★★★★★
()
Ответ на: комментарий от vodz

С остальными переменными все в порядке - код рабочий. Я только пытаюсь найти способ присвоить значение последнему аргументу без использования функции приведения типов.

bigov
() автор топика
Ответ на: комментарий от deadNightTiger

упоротое апи, и указатель на самом деле не указатель, а смещение

улыбнуло. А реально так и выходит. Спасибо.

bigov
() автор топика
Ответ на: комментарий от deadNightTiger

GL_FLOAT это тип элементов массива, это отражается в sizeof(float)

Вона чё, Михалыч. Я в этом не копал, но уж точно покруче упоротость, чем в ioctl() :)

vodz ★★★★★
()
Ответ на: комментарий от andreyu

OpenGL это API. Написанное на ванильном С. Но этот факт не делает невозможным его использользование в современных программах на С++.

bigov
() автор топика

В C я использую следующую конструкцию:

#define OPENGL_BUFFER_OFFSET(offset) ((const GLvoid*)((uintptr_t)(offset)))

Соответственно для C++ будет, что-то вроде:

#define OPENGL_BUFFER_OFFSET(offset) (reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>((offset))))

goto-vlad
()
Ответ на: комментарий от goto-vlad

Сразу видно - товарищ разобрался досконально. Зачет!

bigov
() автор топика
Ответ на: комментарий от O02eg

Спасибо за идею, как вариант можно реализовать, но не «малина» - уж проще и читабельнее писать:

	const GLvoid* n_offset = reinterpret_cast<GLvoid*>(3 * sizeof(GLfloat));

bigov
() автор топика
Ответ на: комментарий от O02eg

Данные он указывает в typed_poiter, в API передаёт из glvoid_pointer.

Это вы точно мне? Если да, то это не union, это перенос приведения типа из вызова во внешнюю переменную опять с тем же привидением. Не вижу «решения» изначального вопроса, которое судя по всему было просто в зацикливании на приведение не к тому типу.

vodz ★★★★★
()
Ответ на: комментарий от bigov

Вариант с union, насколько я помню, решает проблему со strict aliasing.

O02eg ★★★★★
()
Ответ на: комментарий от bigov

OpenGL это API. Написанное на ванильном С. Но этот факт не делает невозможным его использользование в современных программах на С++.

Вас назначили ИО капитана Очевидность?

andreyu ★★★★★
()
Ответ на: комментарий от vodz

Но ведь это у нас C++, а не C. В C это алиас, а в C++ это новый тип.

Это алиас в обоих языках.

xaizek ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.