如何将字符数组变成 uint8_t

How to turn a character array into uint8_t

我有一个正在开发的服务器-客户端应用程序,它基本上可以模拟聊天室。这是学校的作业,协议规范有些严格。

我有一个字符数组,用于存储来自客户端的所有消息。

客户端必须首先将消息的长度作为 uint8_t 发送,然后将消息本身作为字符数组发送。

我的问题是我需要存储在发送实际消息之前发送的 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);

如果您使用的架构中 uint8_ttypedefunsigned char(您很可能是),那么只需使用第一个 char 并进行转换它到 uint8_t:

length = (uint8_t)(message_received[0]);

应该可以。

char可以很容易地转换为uint8_t,但我不明白为什么你需要将长度存储在消息数组中。为什么不能只存储在变量中?

以下是您的客户端和服务器示例,我认为它们有一些小改动,可能会有帮助:

server.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);

A 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', '[=12=]' }
 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 代码将被禁止。您知道您正在使用的平台,并且您知道您的应用程序的目标平台,因此您有责任确保代码对于所有这些平台都是正确的。