[英]Character Constants and Initialization in C
我正在通过一本名为“C Primer Plus”的书学习 C 语言。 目前,我正在阅读 C 数据类型(第 3 章)并有一个问题。
书中写道,
字符常量和初始化
[...] 包含在单引号之间的单个字符是 C 字符常量。 [...] 因为字符实际上是作为数值存储的,所以您也可以使用数值代码来赋值。 [...] 有点奇怪的是,C 将字符常量视为 int 类型而不是 char 类型。 例如,在具有 32 位 int 和 8 位 char 的 ASCII 系统上,代码
char grade = 'B';
将“B”表示为以 32 位单元存储的数值 66,但等级最终以 66 存储在 8 位单元中。
我对这部分的理解是声明语句char grade = 'B';
将其 char 变量和字符常量存储在两个位置,一个是 32 位单元的数值 66 和 8 位单元的 66 变量grade
。 (这有点令人困惑。)然后书中接下来的两句话是:
字符常量的这种特性使得定义一个字符常量成为可能,例如“FATE”,四个独立的 8 位 ASCII 代码存储在一个 32 位单元中。 但是,尝试将这样的字符常量分配给 char 变量会导致仅使用最后 8 位,因此该变量会获得值“E”。
我在这里的理解是,多字符常量是可能的,这与本书开头给出的定义不同。 但是,他们在最后一部分中提到的两个地方中只有一个是可能的。 因为字符常量在 C 中是int
类型,而这里的int
是 32 位,所以 'FATE' 有 4 个字符,每个字符 8 位; 因此,4 * 8 = 32。但一个 char 变量只有 8 位空间,所以唯一的最后一个字母将被存储。
而且,为了应用知识,我试过
/* test.c */
#include <stdio.h>
int main(void)
{
char grade = 'FATE';
printf("%d, %c", grade, grade);
return 0;
}
这在编译时给了我一些警告。 警告是多字符字符常量和隐式常量转换中的溢出。
然后我尝试了“FAT”、“FA”和“F”。 只有“F”有效。
最后,我的问题是:
int
单元只有一个 8 位字节而在包含多字符字符常量的情况下失败? 'B'
是int
类型的值,但它不存储在任何地方,就像 42 不存储在任何地方一样,它是一个数字。 但是,如果您在纸上用十进制写 42,则纸上将占用 2 位数字。 如果你有 42 个苹果,数字 42 不需要写下来,因此它不会占用空间,但你仍然有 42 个苹果......
现在char grade
是一个对象。 一个char
类型的整数值 - 一个小整数(通常是 -128 ... 127, 0 ... 255)可以存储到grade
。
对象就像纸上的一个字段,您可以在其中书写一定长度的文本。 表单上的char
只有该范围内的数字才有足够的空间。 由于 ASCII 'B'
值为 66,它很方便地适合char
的范围。
int
类型的对象可以存储可能更大的整数(可能是 -32768 ... 32767 或 -2147483648 ... 2147483647;即实现定义)。
然后我们来到多字符常量。 与书中声称的不同,C 标准规定 ( C11 6.4.4.4p10 )
[...] 包含多个字符(例如,'ab')的整数字符常量的值 [...] 是实现定义的。 [...]
即一个实现(C 编译器)可以定义FATE
的值,因为它看起来合适。 作者错误地声称该值需要为'F' * 16777216 + 'A' * 65536 + 'T' * 256 + 'E'
,但 C 标准没有这样的要求。 这就是为什么许多编译器会警告使用多字符常量的原因(在您的情况下,您会收到“警告:多字符字符常量 [-Wmultichar]” )* - 因为它们不可移植,即相同的代码不会运行用不同的编译器编译时以相同的方式。
现在,我们假设'FATE'
确实是导致这一数字,即1178686533.现在你会如何写在一个字段号121686533的形式,你可以只写-128 ... 127之间的数字? 同样,行为是实现定义的。 作者的实现将采用该数字模 256,这将导致69
,这是E
字母的 ASCII 代码,但确切的行为再次取决于编译器实现。
为了警告该实现定义的行为,编译器发出类似警告:从 'int' 到 'char' 的转换中的溢出将值从 '1178686533' 更改为 '69' 。
主要的收获是:如果你打算在char grade
存储单词FATE
的最后一个字母,你可以这样做:
char grade = 'E';
作者这样做的方式可能会导致某些编译器将作者的书评为F
级......
首先,你需要了解字面常量。通常,我们使用一个后缀来告诉计算机字面常量属于什么类型的字面常量。 比如, 123
10LLU
999L
。 字符常量是文字常量之一。
C 把所有的字符常量都当作int
类型(但它实际上还没有存储在内存中)。并且声明的变量类型决定了存储空间的大小。
char c = 'abc';
计算机将abc
视为 int 类型,但 char 的大小只有一个字节,因此存储的最后一个内容是 'c'(或 'a',取决于您的编译器)
printf("%c", character);
最后,C 将所有字面常量视为int
类型(或 unsigned int、long int ....)。但是,存储的细节仍然取决于声明的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.