C语言:为什么int变量可以存储char?

时间:2017-10-01 23:28:13

标签: c

我最近正在阅读Kernighan的C编程语言。

有一个例子将变量定义为int类型,但使用getchar()存储在其中。

int x;
x = getchar();

为什么我们可以将char数据存储为int变量? 我唯一能想到的就是ASCII和UNICODE。 我是对的吗?

5 个答案:

答案 0 :(得分:5)

由于intgetchar函数(和类似字符输入函数)返回EOF。在某些情况下(char) EOF != EOF(例如charunsigned类型时)。

此外,在许多使用char变量的地方,无论如何它都会默默地promotedint。包含常量字符文字的Ant,如'A'

答案 1 :(得分:1)

getchar是一个旧的C标准函数,当时的哲学更接近于语言如何转换为汇编而不是类型的正确性和可读性。请记住,编译器并没有像现在这样优化代码。在C中,int是默认的返回类型(即如果你没有在C中声明一个函数,编译器会认为它返回int),并且返回一个值就完成了使用寄存器 - 因此返回char而不是int实际上会生成额外的隐式代码来掩盖值的额外字节。因此,许多旧的C函数更喜欢返回int

答案 2 :(得分:1)

C要求int至少与char一样多。因此,int可以存储与char相同的值(允许签名/无符号差异)。在大多数情况下,intchar大很多。

char是一个整数类型,用于存储来自实现定义字符集的字符代码,该字符代码需要与C的抽象基本字符集兼容。 (ASCII符合条件,编译器允许的source-charset和execution-charset也是如此,包括你实际使用的那个。)

有关整数类型的大小和范围(包括char),请参阅<limits.h>。这是别人的limits.h

答案 3 :(得分:1)

getchar()尝试从标准输入流中读取一个字节。返回值可以是unsigned char类型(从0UCHAR_MAX)的任何可能值,也可以是指定为负数的特殊值EOF

在大多数当前系统中,UCHAR_MAX255,因为字节有8位,EOF定义为-1,但C标准不保证这一点:系统有较大的unsigned char类型(9位,16位......),尽管我从未见过它,但EOF被定义为另一个负值。

getchar()(或getc(fp))的返回值存储到char会阻止正确检测文件结尾。考虑这些情况(在常见系统上):

  • 如果char是8位有符号类型,则字节值255(ISO8859-1字符集中的字符ÿ)具有该值转换为-1char。将此charEOF进行比较将产生误报。

  • 如果char未签名,则将EOF转换为char将生成值255,这与EOF不同,从而阻止检测文件结尾。

这些是将getchar()的返回值存储到int变量中的原因。一旦文件结束测试失败,该值稍后可以转换为char

如果int类型已签名且char的值超出{{1}的范围,则将char存储到int会有实施定义的行为}类型。这是一个技术问题,应该强制char类型为无符号,但C标准允许签署char类型的许多现有实现。这种简单的转换会产生意想不到的行为,这需要恶意的实施。

char的值确实取决于执行字符集。大多数当前系统使用ASCII或一些ASCII扩展,如ISO8859-x,UTF-8等。但C标准支持其他字符集,如EBCDIC,其中小写字母不形成连续范围。

答案 4 :(得分:-1)

C被设计为一种非常低级的语言,因此它非常接近硬件。通常,经过一些经验,您可以预测编译器将如何分配内存,甚至可以准确地预测机器代码的外观。

你的直觉是对的:它回归到ASCII。 ASCII实际上是一个简单的1:1映射,从字母(在人类语言中有意义)到整数值(可由硬件处理);对于每个字母,都有一个唯一的整数。例如,'字母'CTRL-A由十进制数'1'表示。 (由于历史原因,许多控制字符首先出现 - 因此CTRL-G在旧的电传终端上敲响了铃声,是ASCII码7.大写'A'和剩下的25个UC字母从65开始,所以请参阅http://www.asciitable.com/以获取完整列表。)

C允许您将变量强制转换为其他类型。换句话说,编译器关心(1)var的内存大小(参见K&amp; R中的'pointer arithmetic'),以及(2)你可以对它做什么操作。

如果内存对我有用,你就不能对char进行算术运算。但是,如果你把它称为int,你可以。因此,要将所有LC字母转换为UC,您可以执行以下操作:

char letter;
....
if(letter-is-upper-case) {
    letter = (int) letter - 32;
}

如果在添加/减去之前没有将var重新解释为int,则某些(或大多数)C编译器会抱怨。

但是,最后,类型'char'只是int的另一个术语,实际上,因为ASCII为每个字母分配一个唯一的整数。