繁体   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