繁体   English   中英

C 中的字符常量和初始化

[英]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”有效。

最后,我的问题是:

  1. 我对这本书的理解正确吗? 初始化带有字符常量的 char 变量是否需要两个地方来保存其值?
  2. 如果我是对的,为什么要将数值和字符变量分开? 当它被调用时,它是如何完全分离和连接在一起的? 为什么需要两个地方?
  3. 如果我是对的,我的 test.c 是否会因为我的膝上型计算机系统的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级......

  1. 计算机只会识别二进制代码,字符常量不会存储在两个地方,因为它们在计算机中是相同的二进制代码。
  2. 如上。
  3. 计算机将字符常量视为int类型,但实际上将它们存储为char大小的一个字节,因此只保存一个字节(在您的计算机中它是F,它当然以二进制形式存储)。 打印时,%c 告诉计算机将内容输出为字符,最后显示 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM