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