将C++代码(带有指针和位移位)转换为 C#



我目前正在参与一个将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 套接字类)

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

谢谢

原始代码可能假设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;

我会尝试添加一些注释以澄清

//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
    }
}

至于你问题的第二部分,看看这个

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

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

在 C# 中看起来像这样

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

等等。

最新更新