在C语言中,字面字符是int还是char类型?

12

如果我声明了这个:

int i = 0 + 'A';

'A'被认为是char还是int

有些人可能会使用:

int i = 0 + (int)'A';

但这真的有必要吗?


6
不需要后者。字符字面量的类型为“int”。 - WhozCraig
2
即使 'A'char 类型,强制转换在大多数平台上也没有影响。准确地说,如果 'A' 是有符号的 char 类型(无论是 signed char 还是带符号的 char),就永远不会有任何区别;如果 A 是无符号的 char 类型(无论是 unsigned char 还是无符号的 char),那么 intchar 必须具有相同的大小才能看到差异。 - Pascal Cuoq
0 + 有什么用?即使在 0 + 'A' 中,它也没有作用,甚至在 0 + (int)'A' 中作用更小。 - Jens Gustedt
"A" 是一个 char 类型,而 char 是一种数值类型。根据标准的 C 强制转换规则,在与 int 结合使用时,它将被隐式转换为 int。 - Hot Licks
2
@HotLicks 'A' 是一个 int。C99 6.4.4.4:10 “整型字符常量的类型为 int。” - Pascal Cuoq
显示剩余2条评论
3个回答

15
在 C 语言中,像 'A' 这样的字符常量的类型是 int。而在 C++ 中,它们的类型是 char
在 C 中,字符常量的类型很少有关系。它保证是 int 类型,但如果将语言更改为 char 类型,则大多数现有代码仍将正常工作。(显式引用 sizeof 'A' 的代码行为会发生变化,但除了尝试区分 C 和 C++ 之外,并没有太多意义,而且还有更好、更可靠的方法来实现这一点。涉及宏的情况下,sizeof 'A' 可能是合理的;我不会在这里详细介绍。)
在你的代码示例中:
int i = 0 + 'A';

0int 类型,而 + 的两个操作数会被提升(如果需要)到一个公共类型,因此无论哪种方式行为都完全相同。即使是这样:

char A = 'A';
int i = 0 + A;

使用相同的方式进行操作,A(它的类型是char)被提升为int。类型为char的表达式通常会被隐式提升为int,但并不总是如此。

在C++中,字符常量的类型是char——但是相同的提升规则适用。当Stroustrup设计C++时,他为了一致性改变了字符常量的类型(A的类型为int确实有点令人惊讶),并且使得更一致的重载成为可能(C语言不支持)。例如,如果C++字符常量的类型为int,那么这段代码:

std::cout << 'A';

输出'A'的ASCII值为65(除非系统使用EBCDIC),输出A更为合理。

int i = 0 + (int)'A';
在C和C++中,强制类型转换通常是不必要的。在C中,'A'已经是int类型,因此转换没有效果。在C++中,它是char类型,但是即使没有强制类型转换,它也会被隐式地转换为int类型。
在C和C++中,应该谨慎地使用强制类型转换。这两种语言在许多情况下提供了隐式转换,这些转换通常能够做正确的事情。显式转换要么覆盖隐式转换,要么创建本来不会发生的转换。在许多(但并非全部)情况下,类型转换的问题最好通过使用语言提供的隐式转换或更改声明来解决,以便被转换的内容在第一次就是正确的类型。
(正如Pascal Cuoq在评论中提醒我,如果普通的char是无符号的,并且与int一样宽,则char类型的表达式将被提升为unsigned int,而不是int。这只有在CHAR_BIT >= 16的情况下才会发生,即如果实现具有16位或更大的字节,并且sizeof(int) == 1,并且普通的char是无符号的。我不确定是否实际存在这样的实现,尽管我了解某些DSPs的C编译器确实具有CHAR_BIT > 8。)

1
你有什么参考资料吗?回答非常准确和优美!你是老师吗? - Grijesh Chauhan
1
MISRA C委员会对__没有隐式转换__非常严格,许多行业现在使用MISRA C进行质量检查。 - Steve Barnes
@PascalCuoq:你的第一条评论:不,我没有。你的第二条评论:与+运算符不同,强制类型转换运算符不会提升其参数;在C++中,(int)'A'确实将操作数从char转换为int。(在许多但不是所有情况下;无论如何都会发生转换;在char c ='A';中,没有提升。) - Keith Thompson
@SteveBarnes:在C或C++中避免隐式转换非常困难(除非有编译器选项可以强制执行)。即使是 char c = 'A' 也会违反这个规则。 - Keith Thompson
1
你需要阅读6.3开头的内容和脚注。你所引用的句子仅适用于发生整数提升的情况。转换操作数不属于这些上下文。类似地,在赋值语句中:char x = ..., y = ...; x = y;y 的值不会被提升为 int,然后再转换回 char;它只是作为 char 赋值。重点是 C 不要求支持对比 int 更窄的类型进行算术操作;但其他操作是必需的。 - Keith Thompson
显示剩余6条评论

10
在 C 语言中,'A' 类型是 int(而不是 char)。我认为有些人在 C++ 中执行 int i = 0 + (int)'A';(或者让代码同时适用于 C++/C)。

3
在C++中,'A'是字符类型(而不是整数类型):在C++和C中都尝试执行sizeof('A')sizeof(int)sizeof(char) - Grijesh Chauhan
@carlos 有些人可能会这样做,因为他们不知道在C语言中'A'是整型。这是很可能的(即使在C++中也因为隐式转换而不需要强制转换)。 - Grijesh Chauhan
1
@carlos 适用于C代码C++代码 - Grijesh Chauhan

0
根据ISO C99标准,C语言中文字面值的类型是int。
然而,像'c'这样的字面字符只需要一个char类型就可以存储。
因此,你可以将字面字符赋值给char变量而不会丢失信息。
 char c = 'c'; /* 'c' is int, but (c == 'c') is true */

你在混淆这个问题和另一个问题“为什么一些C标准库函数返回一个int?”这两个问题完全不同。回答“为什么一些C标准库函数返回一个int?”的问题涉及到类型unsigned char。你的回答对于任何一个问题都没有意义。 - Pascal Cuoq
我删除了EOF段落。我认为其余部分都没问题。 - pablo1977

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