[英]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.