我在我的程序中有以下代码:
char ch='abcd';
printf("%c",ch);
输出结果为d。
我不明白为什么char变量在声明时可以接受4个字符而不会出现编译错误。
注:超过4个字符会出现错误。
我在我的程序中有以下代码:
char ch='abcd';
printf("%c",ch);
输出结果为d。
我不明白为什么char变量在声明时可以接受4个字符而不会出现编译错误。
注:超过4个字符会出现错误。
'abcd'
被称为多字符常量,其具体值由实现定义,这里编译器返回 'd'。
如果您使用 gcc 编译您的代码时添加 -Wmultichar
或 -Wall
参数,gcc 将对其发出警告。
'abcd'
作为整数字符常量是标准的。但由于其值是实现定义的,因此会出现可移植性问题。 - chux - Reinstate Monica我不明白为什么char变量在声明时可以接受4个字符而不会出现编译错误。
它并没有将4个字符压缩成一个char。多字符常量'abcd'是int类型,然后编译器进行常量转换将其转换为char(在此情况下发生溢出)。
假设您知道您正在使用多字符常量以及它是什么。
我现在不使用VS,但我的看法是,4个字符的多字符常量被打包成一个int
,然后向下转换为char
。这就是为什么它被允许的原因。由于将多字符常量打包到整数类型中的顺序是由编译器定义的,因此它可以像您观察到的那样行为。
由于多字符常量旨在用于填充整数类型,因此您可以尝试8字节长的多字符常量。我不确定VS编译器是否支持它,但有很大的机会,因为它适合64位long
类型。
它可能应该发出警告,指出尝试将值文字装入过大的类型。这有点像unsigned char leet = 1337;
。但是,我不确定在VS中如何工作(它是否触发警告或错误)。
4个字符不是被放入一个char
变量中,而是被放入一个int
字符常量中,然后再赋值给一个char
。
C标准的3个部分(C11dr §6.4.4.4)可能会有所帮助:
“整数字符常量是一个或多个多字节字符序列,用单引号括起来,例如'x'。”
“整数字符常量的类型为int
。”
“包含多个字符(例如'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个字符的 int
,int x = 'abcdefgh';
是可能的。
考虑到 int
只保证具有最小范围 -32767 到 32767,超过2的任何值都不具可移植性。
即使是 int = 'ab';
的字节序也会引起问题。
像'abcd'
这样的字符常量通常被错误地使用,因此许多编译器都有一个警告,建议启用以标记这种不常见的C语言结构。
char
,并且总是打印最后一个。 - Sufian Latifint
和“更大”的类型。你是在暗示char
会被扩展成int
或者其他什么吗?否则的话,它无法将多个字符打包到char
类型中,否则会导致内存溢出。我认为这只是编译器的行为,跳过了多字符常量中除最后一个字符以外的所有内容。除了询问多字符常量之外,你能详细说明链接的问题与此问题的关系吗? - luk32