这个问题最初出现在我的related question,我在阅读一些代码时遇到了麻烦。答案结果是这一行
&((GLushort *)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]]
评估为指针。它用于
glDrawElements(GL_TRIANGLES, i32Tris * 3, GL_UNSIGNED_SHORT, &((unsigned short*)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]]);
被解释为偏移以绘制顶点索引的子集。
我的代码目前要求我手动完成openGL在glDrawElements中所做的一些操作,而我无法弄清楚如何将指针用作偏移量。 glDrawElements使用索引数组(在我的代码中名为vertexIndices),所以我尝试过这样的事情:
vertexIndices[&((GLushort *)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]]]
但显然失败了。
编辑1:
我只是试了这个并且编译了......但仍然不确定它是否正确。 vertexIndices + (uint) &((GLushort *)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]]
答案 0 :(得分:6)
在C中偶尔会使用这种习惯用法。将计算封装在宏中是一种好习惯,但这是一个副作用。
您遇到的麻烦是:是的,表达式的类型是指针类型,但表达式的解释(如您所知)是一个偏移量。因此,表达式值仅在转换为int时有效。
在glDrawElements()
调用中,表达式值被C的参数规则强制转换为int。
在数组索引中,没有强制规则可以自动将表达式转换为int。你必须提供int cast:
vertexIndices[(int)&((GLushort *)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]]]
更好的形式是:
#define OFFSET_OF_GLUSHORT_STUFF (m, N) \ ((int)&((GLushort *)0)[3 * (m).sBoneBatches.pnBatchOffset[(N)]]) /*...*/ vertexIndices[OFFSET_OF_GLUSHORT_STUFF(mesh, batchNum)];
WHOA,您刚刚更改了问题,表明您正在尝试使用此偏移来计算指向数组元素的指针。在这种情况下,请勿使用这种基于偏移的方法,因为如果要传递兼容的指针类型,指针数学应该直接工作。如果你没有传递兼容的指针类型,那么就会发生破坏。
为了您的代码安全,您必须使用一些直接指针数学来实现此功能。
答案 1 :(得分:2)
传递给glDrawElements
的是指向偏移量的指针,而不是指针作为偏移量。你神秘的代码行相当于:
size_t offset = ((GLushort*)0)[3 * mesh.sBoneBatches.pnBatchOffset[batchNum]];
glDrawElements(GL_TRIANGLES, i32Tris * 3, GL_UNSIGNED_SHORT, &offset);
换句话说,glDrawElements()
没有直接使用第四个参数作为偏移量,而是指向偏移值的指针。这从OpenGL documentation可以清楚地看出,它具有glDrawElements的以下签名:
void glDrawElements( GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices );
并解释:
indices - 指定指向存储索引的位置的指针。
(强调我的。)
除此之外:偏移计算有点奇怪,但是对于您的其他问题的答案中列出的原因有效。将其写成:
更清晰,风格更正常size_t offset = sizeof(GLushort) * 3 * mesh.sBoneBatches.pnBatchOffset[batchNum];
答案 2 :(得分:1)
基于零偏移的计算可以在某些编译器中工作,但保证不能这样做。 ANSI C在stddef.h
中为您提供the offsetof
operator,以允许您计算结构成员的偏移量。