如何将字符数组转换为 uint8_t
Posted
技术标签:
【中文标题】如何将字符数组转换为 uint8_t【英文标题】:How to turn a character array into uint8_t 【发布时间】:2017-03-27 13:38:28 【问题描述】:我正在开发一个服务器-客户端应用程序,它基本上模拟了一个聊天室。这是学校的作业,协议规范有些严格。
我有一个 char 数组,它将存储来自客户端的所有消息。
客户端必须首先将消息的长度作为 uint8_t 发送,然后将消息本身作为 char 数组发送。
我的问题是我需要存储在发送实际消息之前发送的 uint8_t 值,但我只能使用消息数组来存储来自客户端的任何信息。
如果我没记错的话,char 数组不会存储发送过来的 uint8_t,除非我以某种方式强制转换它。
如何将 uint8_t 转换为字符再转换回 uint8_t?
我已尝试在此处查找类似问题,但找不到示例。
server.c
char msg[100];
recv(clients_sd, msg, sizeof(msg), 0);
uint8_t len; /* store the length of the message here */
char message_received[len];
recv(clients_sd, message_received, sizeof(message_received), 0); /* get and store the message here */
client.c
uint8_t length = 21;
char clients_message[] = "Hi how are you today?";
send(servers_sd, &length, sizeof(length), 0);
send(serers_sd, &clients_message, sizeof(clients_message), 0);
【问题讨论】:
【参考方案1】:如果您的架构中uint8_t
是typedef
到unsigned char
(您很可能是这样),那么只需将第一个char
转换为uint8_t
:
length = (uint8_t)(message_received[0]);
它应该工作。
【讨论】:
我会试一试。谢谢!【参考方案2】:char 可以轻松转换为 uint8_t,但我不明白为什么需要将长度存储在消息数组中。为什么不能只存储在变量中?
以下是您的客户端和服务器示例,我认为这些更改可能会有所帮助:
服务器.c
uint8_t len; /* store the length of the message here */
recv(clients_sd, &len, sizeof(len), 0);
char message_received[len];
recv(clients_sd, message_received, len, 0); /* get and store the message here */
client.c
uint8_t length = 21;
char clients_message[] = "Hi how are you today?";
send(servers_sd, &length, sizeof(length), 0);
send(serers_sd, clients_message, length, 0);
【讨论】:
【参考方案3】:char
正好是一个字节(根据 C 标准的定义)。除非字节在您的系统上不完全是 8 位(存在这样的系统,但我敢打赌您从未使用过甚至从未见过),uint8_t
和 char
是完全相同的数据类型。
char c = 5;
uint8_t u = c;
如果你可以对数据类型做类似的事情,那么你可以在这两种数据类型之间随意转换指针:
char c[] = 'H', 'e', 'l', 'l', 'o' ;
uint8_t * u = (uint8_t *)c;
uint8_t x = u[1];
// x is 101, which is the ASCII char code of 'e'
实际上你甚至可以用字符串来做到这一点,因为字符串也只是一个字符数组,只是一个以NUL
终止的字符。
char * c = "Hello";
// "Hello" is in fact just 'H', 'e', 'l', 'l', 'o', '\0'
uint8_t * u = (uint8_t *)c;
uint8_t x = u[1];
// x is 101, which is the ASCII char code of 'e'
唯一需要注意的是,C 标准没有定义 char
是有符号还是无符号。与默认有符号且仅在您请求时才无符号的整数类型不同(例如long
与unsigned long
),char
默认可能有符号或无符号。因此,如果您需要其中任何一个,则必须使用signed char
或unsigned char
作为数据类型。在实践中,除非您对 char
值执行某些数学或逻辑运算(在现代 C 代码中您可能一开始不应该这样做),否则它不会起作用。
而且由于您的消息不可能大于 256 个字符(否则长度将不适合 uint8_t
)并且长度始终是一个字节,我将编写代码如下:
uint8_t messageLength = 0;
ssize_t bytesRead = recv(clients_sd, &messageLength, 1, 0);
if (bytesRead == -1)
// Handle read error
if (bytesRead == 0)
// Handle end of stream
char message[256];
bytesRead = recv(clients_sd, message, messageLength, 0);
if (bytesRead == -1)
// Handle read error
if (bytesRead == 0)
// Handle end of stream
if (bytesRead < messageLength)
// Handle truncated message (message too small)
再一次,显然有些人已经无法理解我的第二句话:我在上面写的所有内容都是假设您系统上的字节是 8 位长。这段代码不能移植到字节多于或少于 8 位的平台上,这已经是我的第二句话清楚地指出的内容,但这并不会使我的回答出错。如果不允许编写不能移植到地球上所有现有平台的 C 代码,那么 90% 的现有 C 代码将被禁止。您知道您正在使用的平台,并且您知道您的应用所针对的平台,因此您有责任确保代码对于所有这些平台都是正确的。
【讨论】:
uint8_t 不能保证是字符类型的同义词。因此,使用 is 为所有类型(可能是字符类型)设置别名是不可移植的。 @2501 请解释“除非字节在您的系统上不完全是 8 位(这样的系统存在,但我打赌您从未使用过甚至从未见过),uint8_t和 char 是完全一样的数据类型。" 你没看懂吗?你知道除非这个词的意思吗?请不要再把我从未说过的话放在我的嘴里。并且请不要评论您显然没有阅读过的答案。 @2501char
始终是一个字节,C 标准要求这样做!如果您的系统上的一个字节有 8 位(我明确警告说不一定是这种情况!!!),那么uint8_t
也是一个字节。请向世界解释一下,一个字节不能是一个字节,因为C标准也要求如果存在原生8位类型,uint8_t
必须是那个类型,如果char
是8位,那么这样的原生类型必须存在。所以你的评论甚至没有意义。
我没有把任何“话放在你的嘴里”。让我们把它放在一边,因为它不相关。让我引用你的话:uint8_t and char are exactly the same data type.
我已经回复了这个:uint8_t isn't guaranteed to be a synonym for a character type.
因此它们不是同一类型。标准允许 uint8_t 不是字符类型的同义词,无论每个字节有多少位。这是可能的,因为扩展的整数类型。请参阅:当前标准的 7.20 @4。 (如果你想和我辩论,也请不要自找麻烦。)
我所做的评论应该包括您对每字节 8 位的假设。这不是我的论点的问题,因为结论是相同的。 C 标准允许将 uintN_t 类型定义为与字符类型不同的扩展整数类型(当前标准的 7.20 §4)。无论每个字节有多少位,这都是正确的。因此,实现可以定义每字节 8 位和 uint8_t 作为扩展整数类型,这是一种不同的类型。以上是关于如何将字符数组转换为 uint8_t的主要内容,如果未能解决你的问题,请参考以下文章
将 unsigned char 数组转换为 uint8_t 数组?
将 Intrinsic xmm 寄存器转换为 uint8_t 数组[16]