C语言 将 uint16_t 转换为 char[2] 以通过套接字发送(unix)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13279024/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:21:35  来源:igfitidea点击:

Convert a uint16_t to char[2] to be sent over socket (unix)

csocketsunixtcpstream

提问by Michael Crook

I know that there are things out there roughly on this.. But my brains hurting and I can't find anything to make this work...

我知道这里有一些大致的事情......但是我的大脑受伤了,我找不到任何东西来完成这项工作......

I am trying to send an 16 bit unsigned integer over a unix socket.. To do so I need to convert a uint16_t into two chars, then I need to read them in on the other end of the connection and convert it back into either an unsigned int or an uint16_t, at that point it doesn't matter if it uses 2bytes or 4bytes (I'm running 64bit, that's why I can't use unsigned int :)

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

I'm doing this in C btw

顺便说一句,我在 C 中这样做

Thanks

谢谢

回答by Steven Sudit

Why not just break it up into bytes with mask and shift?

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

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

(edit)

(编辑)

On the other end, you assemble with the reverse:

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

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

Off the top of my head, not sure if that cast is required.

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

回答by Goz

char* pUint16 = (char*)&u16;

ie Cast the address of the uint16_t.

即投射 uint16_t 的地址。

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

c16 now contains the 2 bytes of the u16. At the far end you can simply reverse the process.

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

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

Interestingly though there is a call to memcpy nearly every compiler will optimise it out because its of a fixed size.

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

As Steven sudt points out you may get problems with big-endian-ness. to get round this you can use the htons (host-to-network short) function.

正如 Steven sudt 指出的那样,您可能会遇到大端顺序问题。为了解决这个问题,您可以使用 htons(主机到网络的简称)功能。

uint16_t ui16correct = htons( 0xdead );

and at the far end use ntohs (network-to-host short)

并在远端使用 ntohs(网络到主机的简称)

uint16_t ui16correct = ntohs( ui16 );

On a little-endian machine this will convert the short to big-endian and then at the far end convert back from big-endian. On a big-endian machine the 2 functions do nothing.

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

Of course if you knowthat the architecture of both machines on the network use the same endian-ness then you can avoid this step.

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

Look up ntohl and htonl for handling 32-bit integers. Most platforms also support ntohll and htonll for 64-bits as well.

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

回答by dst2

Sounds like you need to use the bit mask and shift operators.

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

To split up a 16-bit number into two 8-bit numbers:

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

  • you mask the lower 8 bits using the bitwise AND operator (& in C) so that the upper 8 bits all become 0, and then assign that result to one char.
  • you shift the upper 8 bits to the right using the right shift operator (>> in C) so that the lower 8 bits are all pushed out of the integer, leaving only the top 8 bits, and assign that to another char.
  • 您使用按位与运算符(C 中的 &)屏蔽低 8 位,以便高 8 位全部变为 0,然后将该结果分配给一个字符。
  • 您使用右移运算符(在 C 中为>>)将高 8 位右移,以便将低 8 位全部推出整数,只留下高 8 位,并将其分配给另一个字符。

Then when you send these two chars over the connection, you do the reverse: you shift what used to be the top 8 bits to the left by 8 bits, and then use bitwise OR to combine that with the other 8 bits.

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

回答by Gianluca Ghettini

Basically you are sending 2 bytes over the socket, that's all the socket need to know, regardless of endianness, signedness and so on... just decompose your uint16 into 2 bytes and send them over the socket.

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

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

At the other end do the conversion in the opposite way

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