13

我知道在这方面有一些大致的事情......但是我的大脑很疼,我找不到任何东西来完成这项工作......

我正在尝试通过 unix 套接字发送一个 16 位无符号整数。为此,我需要将 uint16_t 转换为两个字符,然后我需要在连接的另一端读取它们并将其转换回unsigned int 或 uint16_t,此时使用 2bytes 或 4bytes 都没有关系(我正在运行 64bit,这就是为什么我不能使用 unsigned int :)

我在 C 顺便说一句

谢谢

4

4 回答 4

37

为什么不直接用掩码和移位把它分解成字节呢?

 uint16_t value = 12345;
 char lo = value & 0xFF;
 char hi = value >> 8;

(编辑)

在另一端,你用相反的方式组装:

 uint16_t value = lo | uint16_t(hi) << 8;

在我的头顶上,不确定是否需要演员表。

于 2012-11-07T22:10:15.233 回答
3
char* pUint16 = (char*)&u16;

即投射uint16_t的地址。

char c16[2];
uint16_t ui16 = 0xdead;
memcpy( c16, ui16, 2 );

c16 现在包含 u16 的 2 个字节。在远端,您可以简单地反转该过程。

char* pC16 = /*blah*/
uint16_t ui16;
memcpy( &ui16, pC16, 2 );

有趣的是,尽管调用了 memcpy,但几乎每个编译器都会对其进行优化,因为它的大小是固定的。

正如 Steven sudt 指出的那样,您可能会遇到大端序问题。为了解决这个问题,您可以使用 htons(host-to-network short)功能。

uint16_t ui16correct = htons( 0xdead );

并在远端使用 ntohs (network-to-host short)

uint16_t ui16correct = ntohs( ui16 );

在 little-endian 机器上,这会将 short-endian 转换为 big-endian,然后在远端从 big-endian 转换回来。在大端机器上,这两个函数什么都不做。

当然,如果您知道网络上两台机器的架构使用相同的字节序,那么您可以避免这一步。

查找 ntohl 和 htonl 以处理 32 位整数。大多数平台也支持 64 位的 ntohll 和 htonll。

于 2012-11-07T22:08:59.767 回答
2

听起来您需要使用位掩码和移位运算符

要将一个 16 位数字拆分为两个 8 位数字:

  • 您使用按位与运算符(C 中的 &)屏蔽低 8 位,以便高 8 位全部变为 0,然后将该结果分配给一个字符。
  • 您使用右移位运算符(C 中的>>)将高 8 位向右移动,以便将低 8 位全部推出整数,只留下前 8 位,并将其分配给另一个字符。

然后,当您通过连接发送这两个字符时,您会执行相反的操作:将过去的前 8 位向左移动 8 位,然后使用按位或将其与其他 8 位组合。

于 2012-11-07T22:11:32.770 回答
1

基本上,您通过套接字发送 2 个字节,这就是套接字需要知道的所有内容,无论字节顺序、符号等...只需将您的 uint16 分解为 2 个字节并通过套接字发送它们。

char byte0 = u16 & 0xFF;
char byte1 = u16 >> 8;

在另一端以相反的方式进行转换

于 2012-11-07T22:14:01.923 回答