【发布时间】:2021-08-26 05:44:12
【问题描述】:
可以从字符串文字初始化uint8_t 数组吗?它是按预期工作还是由于有符号-无符号转换而破坏了一些字节? (我希望它只是将文字的位原封不动地塞进去。)GCC 不会抱怨 -Wall 并且它似乎有效。
const uint8_t hello[] = "Hello World"
我正在使用一个将字符串作为uint8_t * 的API。现在我正在使用演员表,否则我会收到警告:
const char* hello = "Hello World\n"
HAL_UART_Transmit(uart, (uint8_t *)hello, 12, 50);
// HAL_UART_Transmit(uart, hello, 12, 50);
// would give a warning such as:
// pointer targets in passing argument 2 of 'HAL_UART_Transmit' differ in signedness [-Wpointer-sign]
在这个平台上,char 是 8 位且有符号的。在这种情况下可以使用uint8_t 而不是char 吗?请不要关注 constness 问题,API 应该采用 const uint8_t * 但没有。这个 API 调用只是让我想到这个问题的例子。
令人讨厌的是,这个问题现在已经结束,我想自己回答。抱歉在此处添加此信息,我无权重新打开。
以下所有内容都适用于gcc -Wall -pedantic,但第四个警告关于将有符号转换为无符号。 内存中的位模式将是相同的,如果您将这样的对象转换为(uint8_t *),它将具有相同的行为。根据marked duplicate,这是因为您可以将字符串文字分配给任何 char 数组。
const char string1[] = "Hello";
const uint8_t string2[] = "Hello";
uint8_t string3[] = "Hello";
uint8_t* string4 = "Hello";
char* string5 = "Hello";
当然,只推荐前两个,因为您不应该尝试修改字符串文字。在上面的具体案例中,您可以创建一个包装函数/宏,或者只是将强制转换保留在内部作为对 API 的让步,然后就这样结束了。
【问题讨论】:
-
如果您很确定 char 是 8 位,则不应该。
-
显示函数定义,而不是描述你认为它是什么。也显示确切的警告,而不是“警告”。
-
我更关心将指向非可变数据的指针传递给期望指向可变数据的指针的函数,并将其从警告图表中剔除。如果
HAL_UART_Transmit不打算修改数据,则强制转换为非常量。 -
我添加了警告,尽管它确实与问题无关(即:我可以将字符串文字分配给
uint8_t *或unsigned char *数组,而不是将其分配给char *稍后再进行转换。我试图调用的函数让我想到这个是HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)。 -
@WhozCraig 我同意,但 API 就是这样(使用非常量,但合同是它不会修改数据)。有很多地方你必须对 API 设计中的问题进行有趣的转换。我正试图让我的代码更理智一点。