【问题标题】:get strlen after memcpy in c++在 C++ 中的 memcpy 之后获取 strlen
【发布时间】:2025-12-14 07:40:01
【问题描述】:

我正在尝试使用 memcpy 函数连接一个字符,但是,在几个 memcpy 之后,我的缓冲区长度有点奇怪。请看下面的代码

int main()
{
uint8 txbuffer[13]={0};
uint8 uibuffer[4] = "abc";
uint8 rxbuffer[4] = "def";
uint8 l[2]="g";
int index = 1;

cout << strlen((char*)txbuffer) <<endl;
memcpy(&txbuffer[1],&uibuffer, strlen((char*)uibuffer));
index+=strlen((char*)uibuffer);

cout <<"after first memcpy: "<< strlen((char*)txbuffer) <<endl;
memcpy(&txbuffer[index],&rxbuffer, strlen((char*)uibuffer));

cout <<"after second memcpy: "<< strlen((char*)txbuffer) <<endl;
memcpy(&txbuffer[0],&l, strlen((char*)l));

cout <<"after third memcpy: "<< strlen((char*)txbuffer) <<endl;
for (int i = 0; i < sizeof(txbuffer); i += 1)
{
    cout << (int(txbuffer[i]))<<" : "<< char(int(txbuffer[i]))<<endl;
}
return 0;
}

输出是:

after first memcpy: 0
after second memcpy: 0
after third memcpy: 7
103 : g
97 : a
98 : b
99 : c
100 : d
101 : e
102 : f
0 : 
0 : 
0 : 
0 : 
0 : 
0 :

我的问题是为什么在第一个 memcpy 之后,缓冲区的 strlen 仍然为零?

【问题讨论】:

    标签: c++ memcpy strlen


    【解决方案1】:

    您不应该在 memcpying strlen 原始字节之后 strlen 目的地,因为您没有复制 0 终止符。

    此外,您从字节 1 开始复制,而不是 0,这意味着 strlen 为 0,因为您的数组最初为零(这使我的第一段无关紧要,但您应该注意这一点)。

    【讨论】:

      【解决方案2】:

      这是因为txbuffer 中的第一个字符是空字符\0。 (您以这种方式对其进行了初始化。)因此,当您将字符串打印出来时,它实际上具有零长度。

      您没有覆盖第一个或第二个副本中的第一个字符。但是你最终在第三个副本中覆盖了它。这就是为什么在第三个副本之后长度为零的原因。

      //  Start
      {  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0}
      
      //  After 1st memcpy(): strlen() is still zero
      {  0, 'a', 'b', 'c',   0,   0,   0,   0,   0,   0,   0,   0,   0}
         ^ first null character
      
      //  After 2nd memcpy(): strlen() is still zero
      {  0, 'a', 'b', 'c', 'd', 'e', 'f',   0,   0,   0,   0,   0,   0}
         ^ first null character
      
      //  After 3rd memcpy(): strlen() is now 7
      {'g', 'a', 'b', 'c', 'd', 'e', 'f',   0,   0,   0,   0,   0,   0}
                                            ^ first null character
      

      【讨论】:

        【解决方案3】:

        strlen() 计算非 NUL 字节数。由于初始 NUL 在复制后仍然存在,所以strlen() 当然返回零。

        相反,您可能更喜欢使用sizeof 或更明确的连接逻辑:

        int main()
        {
            char txbuffer[13];
            char uibuffer[4] = "abc";
            char rxbuffer[4] = "def";
            char l[2]="g";
            int index = 1;
        
            int n = sprintf (txbuffer, "%s%s%s", uibuffer, rxbuffer, l);
            cout << "buffer has " << n << " bytes" << endl;
            return 0;
        }
        

        【讨论】:

          【解决方案4】:

          这里有多个问题。

          首先使用 &uibuffer 作为 memcpy 的参数是错误的,只需使用 uibuffer (rxbuffer,l) 因为它们已经是地址(作为数组):

          memcpy(&txbuffer[1], uibuffer, strlen((char*)uibuffer));
          

          在上面的 txbuffer 上做一个 strlen(因为你复制到带有偏移量 1 的 txtbuffer)将产生 0 长度,因为 strlen 计数直到它找到 \0,将 strlen 与 memcpy 结合使用不是一个好主意,而是跟踪您手动在 txtbuffer 中的长度,您知道您复制的字符串的长度和偏移量。

          【讨论】: