为什么C语言中的字符字面量是整型而不是字符型?

120
在C++中,sizeof('a') == sizeof(char) == 1。这个很容易理解,因为'a'是一个字符字面值,而sizeof(char) == 1是由标准定义的。
但在C语言中,sizeof('a') == sizeof(int)。也就是说,C语言中的字符字面值实际上是整数。有没有人知道为什么呢?我能找到很多关于这个C语言怪癖的提及,但没有解释它存在的原因。

sizeof 只会返回一个字节的大小,不是吗?char 和 int 的大小不相等吗? - Josh Smeaton
1
这可能与编译器(和架构)有关。能说一下你在用什么吗?标准(至少到89年)非常宽松。 - dmckee --- ex-moderator kitten
2
一个char类型始终是1字节大小,因此在C++中sizeof('a') == 1总是成立的。而int类型理论上可以是1字节大小,但这需要一个字节至少有16位,这是非常不可能的 :) 因此,在大多数实现中,C++中sizeof('a') != sizeof(int)是非常可能的。 - Johannes Schaub - litb
2
在C语言中,这总是错误的。 - Johannes Schaub - litb
25
在C语言中,“a”是一个整数类型 - 就是这样。 C语言率先创建了规则。 C++改变了这些规则。你可以认为C++的规则更有意义,但是改变C的规则会带来更多的损害而不是好处,因此C标准委员会明智地没有触及这一点。 - Jonathan Leffler
Jonathan,只是为了明确一下 - 我的“在C语言中总是错误”的意思并不是说C语言总是错的 :) 它意味着sizeof('a')== sizeof(int)在C语言中总是成立。你的评论听起来像是在评论我在评论中说的某些内容 :) - Johannes Schaub - litb
11个回答

-1

这只是与语言规范有关的次要问题,但在硬件中,CPU通常只有一个寄存器大小--32位,假设--因此,每当它实际处理char(通过添加,减去或比较它)时,在加载到寄存器时会隐式转换为int。编译器负责在每个操作后正确屏蔽和移位数字,以便如果您将2添加到(unsigned char)254,它将环绕到0而不是256,但在硅内部,它确实是int,直到您将其保存回内存。

这是一种学术观点,因为语言规范无论如何都可以指定8位文字类型,但在这种情况下,语言规范恰好更接近CPU实际执行的操作。

(x86发烧友可能会注意到,例如,有一个本地addh op,它可以在一步中添加短宽寄存器,但在RISC核心内部,这会转换为两个步骤:添加数字,然后扩展符号,就像PowerPC上的add / extsh对一样)


1
又一个错误的答案。这里的问题是为什么字符字面量和char变量有不同的类型。自动提升反映了硬件,但并不相关 - 实际上是反相关的,因为char变量会自动提升,所以字符字面量不应该不是char类型的原因。真正的原因是多字节字面量,现在已经过时了。 - Jim Balter
@Jim Balter,多字节文字并不过时;现在有多字节Unicode和UTF字符。 - Crashworks
@Crashworks 我们正在谈论多字节的字符字面量,而不是多字节的字符串字面量。请注意听讲。 - Jim Balter
4
Chrashworks确实写了_characters_。你应该写明_wide_字符字面量(比如L'à')占用更多的字节,但不被称为多字节字符字面量。减少傲慢态度有助于你提高准确性。 - Blaisorblade
@Blaisorblade,宽字符字面量在这里并不相关——它们与我所写的内容无关。我很准确,而你缺乏理解力,试图纠正我是傲慢的行为。 - Jim Balter
两个问题: 1)UTF的提及是否指的是UTF-8? 2)将单个非ASCII UTF-8字符编码为多字节字符文字是否不可能/过时? 如果两个问题的答案都是肯定的,正如它们似乎是的(无法找到明确的答案),那么我要向您道歉,质疑了您的准确性。 - Blaisorblade

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