我目前正参与一个将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类)
我知道它可以被认为是一个懒惰的问题,但我想也许可以帮助我解决这个问题。
由于
答案 0 :(得分:2)
我会尝试添加一些注释以澄清
//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
答案 1 :(得分:2)
原始代码可能假设sizeof(int)
为4,标准无法保证。无论如何,它使用第一个字节来保存CMND_MOVEL
和CMD_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;
答案 2 :(得分:1)
卢卡斯已经涵盖了大部分内容;但它实际上正在做的是使用指针数学移动数组。所以这个:
dst++;
*dst = 10 * LastDestination.x;
C#中的看起来像这样
var arrayIndex = 0;
CmndBuffer[arrayIndex++] = 10 * LastDestination.x;
CmndBuffer[arrayIndex++] = 10 * LastDestination.y;
等等。