簡體   English   中英

C ++指針數學

[英]C++ Pointer Math

有關於C ++指針添加的問題。 如果您查看提供的屏幕快照,基本上可以看到我正在執行memcpy(m_pBuf + m_iWritePtr ....並且此內存指針添加未按預期方式工作。

我以為添加m_pBuf + m_iWritePtr會將m_iWritePtr字節添加到我的內存地址m_pBuf中。 m_pBuf是指向結構數組的指針; 即(T *)m_pBuf = new T [cnt]其中T是類型名,cnt是分配的T個對象的數量。 在這種情況下,T是一個簡單的結構。 在這種情況下,sizeof(T)為260。

memcpy調用引發錯誤,我知道指針數學是錯誤的,但我不確定100%為什么。 我認為,將memcpy編碼為采用基地址並添加一些n * 260字節以獲取緩沖區的偏移量。 注意:當這不是模板實現並且T只是一個char *時,此代碼將起作用。 現在T是某種類型名稱的模板,偏移量的添加不再按預期的方式工作。

因此,如果您看下面的屏幕截圖,這是我使用編譯器的調試器/檢查器和計算器進行的各種計算/引用的結果:

The memory address of m_pBuf     = 0x01E7E0E0

The memory address of m_pBuf[1]  = 0x01E8EE04
the memory address of m_pBuf+1     = 0x01E8EE04
the memory address of m_pBuf++     = 0x01E8EBFC  
the memory address of m_pBuf+260   = 0x01E7E1E4 (the calculator's result)

我試圖了解這里發生了什么。 前兩個似乎正確,但我不明白為什么這些都不相等。 這是Windows 7-64位上的32位編譯器。

在此處輸入圖片說明

為了進一步說明,這是類型為T的環形緩沖區,其大小為n * T個存儲對象。 這是代碼:

template<typename T>
bool TMsgBuffer<T>::PutMsgEx(T *pBuf, unsigned long nObjCount )
{
 bool bResult = false;
 unsigned long MaxWriteSize, nPutLen;

 Lock();

 MaxWriteSize = GetMaxWriteSize();  // this returns size of my buffer in total.
 nPutLen = nObjCount * m_nObjSize;  // m_nObjSize is set else where to sizeof(T)


 if(nPutLen <= MaxWriteSize)
 {
     // easy case, no wrapping
     if( m_iWritePtr + nPutLen <= m_nBufSize )
     {
         memcpy(m_pBuf + m_iWritePtr, pBuf, nPutLen);
         m_iWritePtr += nPutLen;
     }
     else // need to wrap
     {
         m_iFirstChunkSize = m_nBufSize - m_iWritePtr;
         m_iSecondChunkSize = nPutLen - m_iFirstChunkSize;

         memcpy(m_pBuf + m_iWritePtr, pBuf, m_iFirstChunkSize );
         memcpy(m_pBuf, pBuf + m_iFirstChunkSize, m_iSecondChunkSize );

         m_iWritePtr = m_iSecondChunkSize;
     }

     //m_MsgCount++;
     m_MsgCount+= nObjCount;
     bResult = true;
 }

 Unlock();

 return bResult;
}

指針數學以邏輯方式工作。 當將n添加到類型為Foo的指針時,它會使指針的sizeof(Foo) * n個字節,而不是n個字節。 無論如何,為什么還要將一個指針添加到另一個指針? 您試圖通過此操作完成什么?

請注意操作順序。 我猜你是先做++的:

m_pBuf++     = 0x01E8EBFC

postincrement的作用是更改值,但打印出舊值 ,因此,如果您打印了m_pBuf,我想您會得到0x1E8ED00。

如果你跑了

m_pBuf+1     = 0x01E8EE04

新值正確(差異為sizeof(T)= 260)

顯示附近的代碼,並確保您謹慎對待帶有副作用的語句。

正如Ed和Martin所說,指針數學涉及指針類型的大小。

在指針上加1會使指針的地址增加類型的大小。

現在,您沒有提到的一件事就是m_pBuf的類型。

但是在您的調試會話中,編譯器/調試器認為`(char *)&m_pBuf [1]-(char *)m_pBuf == 0x01E8EE04-0x01E7E0E0 == 0x10D24 == 68900(十進制)

68900/260(sizeof T)== 265

因此,編譯器/調試器認為m_pBuf為T [265]。

但是正如Foo Bah指出的那樣, m_pBuf++修改了指針。 所以兩個視圖調試器表達式m_pBuf[[1]]m_pBuf+1后可能發生m_pBuf++由於用於窗口m_pBuff++表示比其它兩種測試表達式較小的值。

針對這種情況進行重新調整,我們最終得到m_pBuf為T [263]。

如果要從m_pBuf的開頭訪問前T個字節,則可以在執行指針算術之前將m_pBuf(char *) 最有可能是更優雅的解決方案,但您尚未顯示足夠的代碼-這些令人討厭的調試器表達式窗口掩蓋了重要內容!

這可能有助於發布代碼。

請記住,增加類型T的指針會使它增加sizeof(T)個字節。

讓我猜測: m_pBuf不是T*的指針,而是T[265]的指針,對嗎? 這是m_pBuf+1等於(char*)m_pBuf + 260*265地址的唯一方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM