2009-11-02 175 views
1

這個問題最初出現在我的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

我想我對'指針作爲偏移量'的整個想法並不是很滿意。我想我可以把所有的指針都看作0的偏移量,但是這對我的語法仍然沒有幫助:-p。 – spencewah 2009-11-02 21:42:21

+0

當我看到您的原始問題時,我想現在我想的是同樣的東西 - 當您的頂點數組不是有效的內存地址時,如果它試圖訪問傳入的頂點數組,glDrawElements不會崩潰(並且僅僅是一個偏移量)? – 2009-11-02 21:54:50

+0

我很抱歉,這個問題對於細節有點簡單,它是另一個問題的擴展(在後面有鏈接),它充分探討了爲什麼glDrawElements在傳遞這個無效內存地址時不會崩潰。 – spencewah 2009-11-02 22:24:54

回答

6

這種成語在C語言中偶爾使用。將計算封裝在宏中是一種好習慣,但這是一個側面問題。

你遇到的麻煩是這樣的:是的,表達式的類型是一個指針類型,但表達式的解釋(如你所知)是一個偏移量。因此,表達式值僅在轉換爲int時有效。

glDrawElements()調用中,表達式值被C的參數規則強制爲int。

在數組索引中,沒有強制規則會自動將表達式轉換爲int。您必須提供INT投:

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)]; 

哇,你只是改變了你的問題,表明你要使用這個偏移量來計算指針到一個數組元素。在這種情況下,不要使用這種基於偏移量的方法,因爲如果你傳遞了一個兼容的指針類型,指針數學應該直接工作。如果你沒有傳遞兼容的指針類型,那麼浩劫就會隨之而來。

爲了您的代碼的安全性,您必須使用某些直接指針數學來獲得此工作。

+0

像魅力一樣工作,謝謝 – spencewah 2009-11-02 22:20:51

+0

不客氣。快樂的繪畫! :) – 2009-11-02 22:22:34

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); 

而且解釋:

指數 - 指定指針,它指向索引的存儲位置

(重點煤礦。)

旁白:偏移計算是有點怪異,但有效的答案概括到其他問題的原因。這是更清晰,更文體正常寫爲:基於一個

size_t offset = sizeof(GLushort) * 3 * mesh.sBoneBatches.pnBatchOffset[batchNum]; 
+0

啊,對不起,我應該提到我使用的是頂點緩衝對象,並且在這種特殊情況下(因爲它是服務器端計算),OpenGL使用指針AS偏移量,而不是像在客戶端計算中那樣使用實際指針(如glDrawArrays) – spencewah 2009-11-02 22:22:55

+0

來自opengl.org: 已解決:當默認緩衝區對象(對象爲零)爲 時,所有指針的行爲都與實際指針相同。當綁定任何其他 對象時,所有指針都被視爲偏移量。 在概念上,可以想象,緩衝區對象零是一個緩衝區 座標爲NULL的對象,並且具有足夠大的範圍,以覆蓋所有系統的虛擬地址空間。 請注意,這種方法基本上要求綁定點是客戶端(非服務器)狀態。 – spencewah 2009-11-02 22:26:19

1

計算在一些編譯器偏移的零可以工作,但不保證這樣做。 ANSI C爲您提供the offsetof operator in stddef.h以允許您計算結構成員的偏移量。