我想知道是否有任何方法可以使用struct和union方法将"5ABBF13A000A01"
之类的字符串转换为下一个结构:
struct xSensorData2{
unsigned char flags;
unsigned int refresh_rate;
unsigned int timestamp;
};
数据应该是:
flags = 0x01 (last byte);
refresh_rate = 0x000A (two bytes);
timestamp = 5ABBF13A (four bytes);
我在考虑下一个数据结构:
struct xData{
union{
struct{
unsigned char flags:8;
unsigned int refresh_rate:16;
unsigned int timestamp:32;
};
char pcBytes[8];
};
}__attribute__ ((packed));
但是我得到了一个12字节的结构,我认为这是因为位字段不适用于不同类型的数据。我应该将字符串转换为十六进制数组,复制到pcBytes
并访问每个字段。
更新: 在stm32平台中,我使用了这段代码:
bool bDecode_HexString(char *p)
{
uint64_t data = 0; /* exact width type for conversion
*/
char *endptr = p; /* endptr for strtoul validation */
errno = 0; /* reset errno */
data = strtoull (p, &endptr, 16); /* convert input to uint64_t */
if (p == endptr && data == 0) { /* validate digits converted */
fprintf (stderr, "error: no digits converted.\n");
return false;
}
if (errno) { /* validate no error occurred during conversion */
fprintf (stderr, "error: conversion failure.\n");
return false;
}
//printf ("data: 0x%" PRIx64 "\n\n", data); /* output conerted string */
sensor.flags = data & 0xFF; /* set flags */
sensor.rate = (data >> CHAR_BIT) & 0xFFFF; /* set rate */
sensor.tstamp = (data >> (3 * CHAR_BIT)) & 0xFFFFFFFF; /* set timestamp */
return true;
/* output sensor struct */
// printf ("sensor.flags : 0x%02" PRIx8 "\nsensor.rate : 0x%04" PRIx16
// "\nsensor.tstamp: 0x%08" PRIx32 "\n", sensor.flags, sensor.rate,
// sensor.tstamp);
}
并调用函数:
char teste[50] = "5ABBF13A000A01";
bDecode_HexString(teste);
我得到data = 0x3a000a01005abbf1
答案 0 :(得分:2)
如果您仍然在努力将输入分离到flags, rate & timestamp
,那么评论中有关使用无符号类型将输入字符串转换为值的建议,并使用提供的确切宽度类型<stdint.h>
,将避免操纵签名类型所固有的潜在问题(例如潜在的符号扩展等)
如果你想分离值并在struct中协调它们,那就100%了。这项工作分离了个人flags, rate & timestamp
。您如何选择存储它们以便在代码中方便,取决于您自己。使用精确宽度类型的简单结构可以是:
typedef struct { /* struct holding sensor data */
uint8_t flags;
uint16_t rate;
uint32_t tstamp;
} sensor_t;
在使用char *
从uint64_t
转换为strtoull
后,您有两项主要验证检查:
利用指向要转换的字符串的指针和endptr
参数来验证数字实际上是否被转换(strtoull
将endptr
设置为点1之后的字符最后一位数转换)。您可以使用它来将endptr
与转换数据的原始指针进行比较,以确认发生了转换(如果没有转换数字,原始指针和endptr
将是相同的,并且返回的值将是零);以及
您在转化前设置了errno = 0;
,然后在转换后再次检查,以确保在转换过程中没有发生错误。如果strtoull
遇到错误,值超出范围等,则errno
设置为正值。
(如果您有特定的范围验证,例如,您希望将结果存储的尺寸小于转化的尺寸,例如uint32_t
而不是uint64_t
,则需要验证最终值可以存储在较小的类型中
一个简单的方法是:
uint64_t data = 0; /* exact width type for conversion */
...
char *p = argc > 1 ? argv[1] : "0x5ABBF13A000A01", /* input */
*endptr = p; /* endptr for strtoul validation */
errno = 0; /* reset errno */
...
data = strtoull (p, &endptr, 0); /* convert input to uint64_t */
if (p == endptr && data == 0) { /* validate digits converted */
fprintf (stderr, "error: no digits converted.\n");
return 1;
}
if (errno) { /* validate no error occurred during conversion */
fprintf (stderr, "error: conversion failure.\n");
return 1;
}
printf ("data: 0x%" PRIx64 "\n\n", data); /* output conerted string */
最后,将data
中的值分隔为flags, rate & timestamp
的各个值,可以通过简单的移位来完成。 ANDS,例如
sensor_t sensor = { .flags = 0 }; /* declare instance of sensor */
...
sensor.flags = data & 0xFF; /* set flags */
sensor.rate = (data >> CHAR_BIT) & 0xFFFF; /* set rate */
sensor.tstamp = (data >> (3 * CHAR_BIT)) & 0xFFFFFFFF; /* set timestamp */
/* output sensor struct */
printf ("sensor.flags : 0x%02" PRIx8 "\nsensor.rate : 0x%04" PRIx16
"\nsensor.tstamp: 0x%08" PRIx32 "\n", sensor.flags, sensor.rate,
sensor.tstamp);
完全放弃,你可以做类似的事情:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <limits.h>
typedef struct { /* struct holding sensor data */
uint8_t flags;
uint16_t rate;
uint32_t tstamp;
} sensor_t;
int main (int argc, char **argv) {
uint64_t data = 0; /* exact width type for conversion */
sensor_t sensor = { .flags = 0 }; /* declare instace of sensor */
char *p = argc > 1 ? argv[1] : "0x5ABBF13A000A01", /* input */
*endptr = p; /* endptr for strtoul validation */
errno = 0; /* reset errno */
data = strtoull (p, &endptr, 0); /* convert input to uint64_t */
if (p == endptr && data == 0) { /* validate digits converted */
fprintf (stderr, "error: no digits converted.\n");
return 1;
}
if (errno) { /* validate no error occurred during conversion */
fprintf (stderr, "error: conversion failure.\n");
return 1;
}
printf ("data: 0x%" PRIx64 "\n\n", data); /* output conerted string */
sensor.flags = data & 0xFF; /* set flags */
sensor.rate = (data >> CHAR_BIT) & 0xFFFF; /* set rate */
sensor.tstamp = (data >> (3 * CHAR_BIT)) & 0xFFFFFFFF; /* set timestamp */
/* output sensor struct */
printf ("sensor.flags : 0x%02" PRIx8 "\nsensor.rate : 0x%04" PRIx16
"\nsensor.tstamp: 0x%08" PRIx32 "\n", sensor.flags, sensor.rate,
sensor.tstamp);
return 0;
}
示例使用/输出
$ ./bin/struct_sensor_bitwise
data: 0x5abbf13a000a01
sensor.flags : 0x01
sensor.rate : 0x000a
sensor.tstamp: 0x5abbf13a
仔细看看,如果您有其他问题,请告诉我。