c - 用字符串文字初始化 uint8_t 数组是否合法?
问题描述
uint8_t
从字符串文字初始化数组可以吗?它是按预期工作还是由于有符号-无符号转换而破坏了一些字节?(我希望它只是将文字的部分原封不动地塞进去。) GCC 不会抱怨,-Wall
而且它似乎可以工作。
const uint8_t hello[] = "Hello World"
我正在使用一个将字符串作为uint8_t *
. 现在我正在使用演员表,否则我会收到警告:
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 *)
它将具有相同的行为。根据标记的 duplicate,这是因为您可以将字符串文字分配给任何 char 数组。
const char string1[] = "Hello";
const uint8_t string2[] = "Hello";
uint8_t string3[] = "Hello";
uint8_t* string4 = "Hello";
char* string5 = "Hello";
当然,只有前两个是值得推荐的,因为您不应该尝试修改字符串文字。在上面的具体情况下,您可以创建一个包装函数/宏,或者只是将强制转换保留在内部作为对 API 的让步,然后一天结束。
解决方案
C 2018 6.7.9 14 告诉我们“字符类型的数组可以由字符串文字或 UTF-8 字符串文字初始化……”</p>
C 2018 6.2.5 15 告诉我们“这三种类型char
, signed char
, 和unsigned char
统称为字符类型。”</p>
C 2018 6.2.5 4 和 6.2.5 6 表示可能有扩展整数类型。
没有声明任何扩展整数类型都是字符类型。
C 2018 7.20 4 告诉我们“对于此处描述的实现提供的每种类型,<stdint.h>
应声明 typedef 名称......”和 7.20.1 5 告诉我们“当 typedef 名称仅在不存在或存在首字母u
时有所不同时,它们应表示相应的有符号和无符号类型,如 6.2.5 中所述……”</p>
因此,C 实现可以提供一个无符号 8 位类型,它是扩展整数类型,而不是unsigned char
, 并且可以定义uint8_t
为这种类型,然后 6.7.9 14 并没有告诉我们可以初始化这种类型的数组通过字符串文字。
如果一个实现允许您uint8_t
使用字符串字面量初始化一个数组,那么它要么定义uint8_t
为 unsignedchar
或 to unsigned char
,要么定义uint8_t
为扩展整数类型,但允许您将数组初始化为 C 语言的扩展标准。由 C 实现来定义该扩展的行为,但我希望它能够像初始化字符类型数组一样工作。
(可以想象,定义uint8_t
为扩展整数类型并不允许将其视为字符类型可能有助于区分允许为任何对象起别名的字符类型与不允许此类别名的纯整数类型。这可能允许编译器执行额外的优化,因为它知道别名不会发生,或者可能诊断某些错误。)
字符串文字的元素具有类型char
(按 C 2018 5.2.1 6)。C 2018 6.7.9 14 告诉我们“字符串文字的连续字节......初始化数组的元素。” 每个字节都应该以通常的方式初始化一个数组元素,包括根据 C 2018 6.7.9 11 转换为目标类型。对于您显示的字符串"Hello World"
,字符值都是非负的,因此在转换它们时没有问题char
值为uint8_t
. 如果字符串中有负数字符,则应以uint8_t
通常的方式将它们转换为。
(如果您的八进制或十六进制转义序列的值未在 a 中表示char
,则初始化中可能会有一些语言律师的怪异。)
推荐阅读
- swiftui - SwiftUI DatePicker 星期几语言
- google-cloud-platform - 在部署新服务修订期间,Cloud Run 如何处理我的应用程序中运行的内容?
- c++ - getchar() 没有读取完整的字符串
- oracle - 在 pl/sql 中使用 utl_file.put_raw 将陈旧数据写入文件的可能性
- r - R中count包中的renewCount()函数
- python - Keyerror 83 并且试图在数据帧的切片副本上设置一个值
- reactjs - 在反应页面中刷新将其重定向到 /404 页面
- google-apps-script - 复制行时触发错误
- java - Android:选择正确的设置来准备 ActivityResultLauncher 以选择联系人
- tailwind-css - 弹性项目内的导航栏溢出问题