为什么char变量只允许4个字符?

6

我在我的程序中有以下代码:

char ch='abcd';
printf("%c",ch);

输出结果为d。

我不明白为什么char变量在声明时可以接受4个字符而不会出现编译错误。

注:超过4个字符会出现错误。


1
多字符常量警告,请参见https://dev59.com/jWsz5IYBdhLWcg3wpZhF - tristan
这里,我发现甚至可以添加更多的char,并且总是打印最后一个。 - Sufian Latif
我正在使用Visual Studio,它只允许4个字符。无论如何,我已经了解到多字符常量的可接受性,我认为不同的IDE有自己的限制... - user3152736
@tristan 这对 OP 有什么帮助?问题和答案都是关于 int 和“更大”的类型。你是在暗示 char 会被扩展成 int 或者其他什么吗?否则的话,它无法将多个字符打包到 char 类型中,否则会导致内存溢出。我认为这只是编译器的行为,跳过了多字符常量中除最后一个字符以外的所有内容。除了询问多字符常量之外,你能详细说明链接的问题与此问题的关系吗? - luk32
@luk32 我认为那个答案解释了多字符常量的含义。 - tristan
@tristan 是的,我认为OP知道他正在使用多字符常量。好吧,我猜错了。但我仍然认为这非常奇特和有趣,为什么4个字符的多字节常量可以被打包成一个单字节的“char”。我认为这才是问题的真正所在。 - luk32
4个回答

7

'abcd' 被称为多字符常量,其具体值由实现定义,这里编译器返回 'd'。

如果您使用 gcc 编译您的代码时添加 -Wmultichar-Wall 参数,gcc 将对其发出警告。


正确。通常期望使用单个字符来表示“-包含文本”。超出此范围的内容(例如,一个32位寄存器/字,可以容纳4个8位字符)是非标准和不可移植的。如果您真的想一次处理4个字符(单字节或多字节),应该使用字符串(“-包含”)。 - Phil Perry
@Phil Perry 在C11 6.4.4.4 10中,'abcd'作为整数字符常量是标准的。但由于其值是实现定义的,因此会出现可移植性问题。 - chux - Reinstate Monica

1

我不明白为什么char变量在声明时可以接受4个字符而不会出现编译错误。

它并没有将4个字符压缩成一个char。多字符常量'abcd'是int类型,然后编译器进行常量转换将其转换为char(在此情况下发生溢出)。


0

假设您知道您正在使用多字符常量以及它是什么。

我现在不使用VS,但我的看法是,4个字符的多字符常量被打包成一个int,然后向下转换为char。这就是为什么它被允许的原因。由于将多字符常量打包到整数类型中的顺序是由编译器定义的,因此它可以像您观察到的那样行为。

由于多字符常量旨在用于填充整数类型,因此您可以尝试8字节长的多字符常量。我不确定VS编译器是否支持它,但有很大的机会,因为它适合64位long类型。

它可能应该发出警告,指出尝试将值文字装入过大的类型。这有点像unsigned char leet = 1337;。但是,我不确定在VS中如何工作(它是否触发警告或错误)。


0

4个字符不是被放入一个char变量中,而是被放入一个int字符常量中,然后再赋值给一个char

C标准的3个部分(C11dr §6.4.4.4)可能会有所帮助:

  1. “整数字符常量是一个或多个多字节字符序列,用单引号括起来,例如'x'。”

  2. “整数字符常量的类型为int。”

  3. “包含多个字符(例如'ab')或包含不能映射到单字节执行字符的字符或转义序列的整数字符常量的值是实现定义的。”

OP的代码char ch='abcd';是将一个int赋值给char,因为'abcd'是一个int。就像char ch='Z';一样,ch被赋予了'Z'int值。在这种情况下,没有什么奇怪的,因为'Z'的值很好地适合于char。在'abcd'的情况下,该值无法适应char,因此会丢失一些信息。有各种可能的结果。通常在一个字节序平台上,ch的值将为'a',而在另一个平台上,其值将为'd'


'abcd' 是一个 int 值,就像在 int x = 12345; 中的 12345 一样。

size(int) == 4 时,可以为 int 赋予字符常量,例如 'abcd'

size(int) != 4 时,限制发生变化。因此,对于8个字符的 intint x = 'abcdefgh'; 是可能的。

考虑到 int 只保证具有最小范围 -32767 到 32767,超过2的任何值都不具可移植性。

即使是 int = 'ab'; 的字节序也会引起问题。


'abcd'这样的字符常量通常被错误地使用,因此许多编译器都有一个警告,建议启用以标记这种不常见的C语言结构。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接