如何将指针用作偏移量?

时间:2009-11-02 21:42:11

标签: c opengl

这个问题最初出现在我的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]]

3 个答案:

答案 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,以允许您计算结构成员的偏移量。