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

In C11, string literals as char[], unsigned char[], char* and unsigned char*

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

unsigned char *a = "5";

使用此编译器抛出警告说 "pointer targets in initialization differ in signedness",这是非常合理的,因为符号信息可以被丢弃。

但是跟随着

unsigned char b[] = "5";

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

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

C 中字符串字面量的类型是 char[],衰减到 char*。请注意,C 不同于 C++,后者的类型为 const char[].

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

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

An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

表示代码与此相同:

unsigned char b[] = 
{ 
  '5',
  '',
  '',
  '[=10=]'
};

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

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

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


1 初始化的类型规则与赋值相同。 6.5.16.1 "Simple assignment" 适用。

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

其次是数组的初始化。使用字符串文字进行初始化的特殊规则是,使用文字的每个字符的 value 来初始化数组的各个元素。

顺便说一句,除您声明外,字符串文字在 C 中不 const 限定。您无权修改它们,但这并未反映在类型中。