【问题标题】:Convert C++ code (with pointers and bit shifting) to C#将 C++ 代码(带有指针和位移位)转换为 C#
【发布时间】:2014-01-25 09:56:33
【问题描述】:

我目前正在参与一个将 C++ 移植到 C# 代码的项目,但有些片段并不那么容易移植 1 到 1,如下所示:

#define CMND_MOVEL              10
#define CMND_EXTRASIDE          0x80

char CmndBuffer[32];

int *dst;
dst = (int*) &CmndBuffer[0];

*dst = 0;
*dst |= (CMND_MOVEL + (Flags << 8));      
if (BoxSide) *dst |= CMND_EXTRASIDE;

dst++;
*dst = SequenceNr;
dst++;
*dst = 10 * LastDestination.x;
dst++;
*dst = 10 * LastDestination.y;
dst++;
*dst = 10 * LastDestination.z;
dst++;
*dst = Speed * 10;
dst++;
*dst = Accel * 10;    

result = ERR_COMMSOCK;
if (UdpCmdSocket >= 0)
{
    if (sendto(UdpCmdSocket, (const char*) CmndBuffer, 28, 0, (struct sockaddr*)&UdpCmdPeer, sizeof(UdpCmdPeer)) != SOCKET_ERROR)
    {
        // more logic here
    }
}

有人可以详细解释一下这里发生了什么吗?我很清楚指针和位移是如何工作的,但我不能 100% 确定在字节级别上发生了什么。我看到的是它正在填充一个数据包以将其扔到 UDP 上。

但更重要的是:我如何在 C# 中发送这个? (我将使用 .NET Socket 类)

我知道这可以被视为一个懒惰的问题,但我认为 SO 可以帮助我解决这个问题。

谢谢

【问题讨论】:

  • 假设速度等是浮点数,我想Speed * 10 行将保留一位十进制数字。 CMND_MOVEL 的值为 10 可能是为了表明这一点......或者它可能是别的东西。

标签: c# c++ pointers


【解决方案1】:

我将尝试添加一些 cmets 以进行澄清

//some constants for later use
#define CMND_MOVEL              10
#define CMND_EXTRASIDE          0x80

char CmndBuffer[32];

int *dst;
//Load the address of the first element of CmndBuffer into dst;
dst = (int*) &CmndBuffer[0];

//CmndBuffer[0] to zero
*dst = 0;
//this loads (CMND_MOVEL + (Flags << 8) into dst. Flags << 8 means a multiplication with 2^8
*dst |= (CMND_MOVEL + (Flags << 8));      
if (BoxSide) *dst |= CMND_EXTRASIDE;

//go to the next array element. The same applies to the commands below
dst++;
//write the value into the current array element
*dst = SequenceNr;
dst++;
*dst = 10 * LastDestination.x;
dst++;
*dst = 10 * LastDestination.y;
dst++;
*dst = 10 * LastDestination.z;
dst++;
*dst = Speed * 10;
dst++;
*dst = Accel * 10;    

result = ERR_COMMSOCK;
if (UdpCmdSocket >= 0)
{
    if (sendto(UdpCmdSocket, (const char*) CmndBuffer, 28, 0, (struct sockaddr*)&UdpCmdPeer, sizeof(UdpCmdPeer)) != SOCKET_ERROR)
    {
        // more logic here
    }
}

至于你问题的第二部分,请看this

【讨论】:

    【解决方案2】:

    Lukas 已经涵盖了大部分内容;但它实际上正在做的是使用指针数学沿着数组移动。所以这个:

        dst++;
        *dst = 10 * LastDestination.x;
    

    在 C# 中看起来像这样

        var arrayIndex = 0;
        CmndBuffer[arrayIndex++] = 10 * LastDestination.x;
        CmndBuffer[arrayIndex++] = 10 * LastDestination.y;
    

    等等。

    【讨论】:

      【解决方案3】:

      原始代码可能假设sizeof(int) 为4,标准不保证。无论如何,它使用第一个字节来保存CMND_MOVELCMD_EXTRASIDE 位,其余3 个字节保存Flags 的值。布局是这样的:

      -------------------------------------------------------------
      | Flags<<8      | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
      | CMD_MOVEL     | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
      | CMD_EXTRASIDE | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
      -------------------------------------------------------------
      

      C/C++ 中的每个char 都是一个字节,对应于C# 中的byte 类型。作者想发送比这更长的值,所以他们使用int*一次写入4个字节。

      这部分:

      //CmndBuffer[0] to zero
      *dst = 0;
      

      实际上设置为 0 CmndBuffer[0]CmdBuffer[3]。由于它们将dst 指针递增了六次,因此它们最终写入CmdBuffer[27]。最后四个字节似乎带有未初始化的值。

      如果您想逐字节写入,则需要使用位移位和掩码。比如:

      byte[] buffer = /*...*/;
      int index = /*...*/;
      int sequenceNr = /*...*/;
      
      buffer[index] = (byte) (sequenceNr >> 24) & 0xFF;
      buffer[++index] = (byte) (sequenceNr >> 16) & 0xFF;
      buffer[++index] = (byte) (sequenceNr >> 8) & 0xFF;
      buffer[++index] = (byte) sequenceNr & 0xFF;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-06
        • 2010-12-23
        • 2011-01-31
        • 1970-01-01
        • 2020-01-27
        • 1970-01-01
        • 1970-01-01
        • 2017-08-28
        相关资源
        最近更新 更多