在 C11 中,字符串文字为 char[]、unsigned char[]、char* 和 unsigned char*

Posted

技术标签:

【中文标题】在 C11 中,字符串文字为 char[]、unsigned char[]、char* 和 unsigned char*【英文标题】:In C11, string literals as char[], unsigned char[], char* and unsigned char* 【发布时间】:2017-12-21 11:10:09 【问题描述】:

通常字符串字面量是 const char[] 类型。但是当我把它当作其他类型时,我得到了奇怪的结果。

unsigned char *a = "\355\1\23";

使用此编译器会抛出警告说“初始化中的指针目标的符号不同”,这是非常合理的,因为可以丢弃符号信息。

但有跟随

unsigned char b[] = "\355\1\23";

根本没有警告。我认为应该出于上述相同原因发出警告。这怎么可能?

仅供参考,我使用的是 GCC 版本 4.8.4。

【问题讨论】:

在询问有关 C 的问题时,请始终包含 C 标签,否则人们将找不到问题。除非您的问题是与 C11 相关的功能,否则您不应使用 C11 标签。如果是这样,请结合 C 和 C11 标签。我已经修复了帖子。 【参考方案1】:

C 中字符串字面量的类型为char[],衰减为char*。请注意,C 与 C++ 不同,它们的类型为 const char[]

在第一个示例中,您尝试将char* 分配给unsigned char*。这些不是兼容的类型,因此您会收到编译器诊断消息。

在第二个示例中,以下内容适用,C11 6.7.9/14:

字符类型的数组可以由字符串字面量或 UTF-8 字符串初始化 字面量,可选地用大括号括起来。字符串文字的连续字节(包括 如果有空间或数组大小未知,则终止空字符)初始化 数组的元素。

表示代码与此相同:

unsigned char b[] = 
 
  '\355',
  '\1',
  '\23',
  '\0'
;

这也可能产生警告,但它是有效的代码。当涉及到不同整数类型之间的赋值1 时,C 具有宽松的类型安全性,但在涉及指针类型之间的赋值时要严格得多。

出于同样的原因,我们可以写成unsigned int x=1; 而不是unsigned int x=1u;

附带说明一下,我不知道您希望使用值为 355 的八进制转义序列实现什么。也许您打算写 "\35" "5\1\23"


1 初始化的类型规则与赋值相同。 6.5.16.1 “简单赋值”适用。

【讨论】:

我想处理 RAW 图像的字节流。在原始代码中,我使用了 \377。【参考方案2】:

首先是指针的初始化,指针的目标类型必须在签名上一致。

第二个是数组的初始化。使用字符串字面量进行初始化的特殊规则是,采用字面量的每个字符的 value 来初始化数组的各个元素。

顺便说一句,除了您说的以外,字符串文字在 C 中不是 const 限定的。您无权修改它们,但这不会反映在类型中。

【讨论】:

以上是关于在 C11 中,字符串文字为 char[]、unsigned char[]、char* 和 unsigned char*的主要内容,如果未能解决你的问题,请参考以下文章

C ++ 0x中char和Unicode的签名

适合在函数参数中将字符串文字转换为 char * 吗?

为啥仅在某些情况下才能将字符串文字隐式转换为 char* ? [复制]

调用 printf 时隐式转换为 char*

c_cpp 仅ASCII ctype.h实现(C11 / C ++ 11 char32_t)。

将字符串文字分配给 char* [重复]