如何将字符数组转换为 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_ttypedefunsigned 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_tchar 是完全相同的数据类型。

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 是有符号还是无符号。与默认有符号且仅在您请求时才无符号的整数类型不同(例如longunsigned long),char 默认可能有符号或无符号。因此,如果您需要其中任何一个,则必须使用signed charunsigned 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 是完全一样的数据类型。" 你没看懂吗?你知道除非这个词的意思吗?请不要再把我从未说过的话放在我的嘴里。并且请不要评论您显然没有阅读过的答案。 @2501 char 始终是一个字节,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的主要内容,如果未能解决你的问题,请参考以下文章

如何将 uint8_t 数组与 C 中的字符串进行比较?

c char 数组到 uint8_t 数组

将 unsigned char 数组转换为 uint8_t 数组?

将 Intrinsic xmm 寄存器转换为 uint8_t 数组[16]

如何将 stringstream 十六进制字符串字符对转换为单个 uint8_t 等效二进制值

在javascript中如何将字符串转换为数组和数组转换为字符串