表映射如何在C中工作?

时间:2014-08-24 18:50:52

标签: c ascii

我希望这个问题有道理!我目前正在学习C(简单!),我对表映射的工作方式感兴趣。

我使用扩展的ASCII表作为实验。 (http://www.ascii-code.com

例如,我可以创建一个char并将其值设置为代码,如下所示:

char charSymbol = '~';

我也可以像这样指定完全相同的值:

char charDec = 126;  
char charHex = 0x7E; 
char charOct = 0176;
char charBin = 0b01111110;

无论我选择哪种上述声明(如果我正确理解事物),每个变量在内存中保存的值总是完全相同。也就是说,二进制表示(01111110)

我的问题是;编译器是否保留扩展的ASCII表并在编译期间执行二进制值查找?如果是这种情况,程序运行的机器是否也保持扩展的ASCII表,以便知道当程序被要求打印01111110以屏幕显示它打印一个" 〜" ?

4 个答案:

答案 0 :(得分:3)

实际上,从技术上讲,您的文本编辑器是带有ASCII(或Unicode)表的文本编辑器。该文件只是作为一个字节序列保存;编译器实际上并不需要有一个ASCII表,它只需要知道哪些字节做了什么。 (是的,编译器在逻辑上将字节解释为ASCII,但是如果你查看编译器的机器代码,你所看到的是一堆字节与固定字节值的比较)。

另一方面,正在执行的计算机有一个ASCII表某处,用于将程序输出的字节映射为可读字符。该表可能在您的终端仿真器中。

答案 1 :(得分:3)

对于您问题中的大多数代码,不需要ASCII查找表。

请注意,在C中,char是一个整数类型,就像int一样,但更窄。像'x'这样的字符常量(由于历史原因)的类型为int,而基于ASCII的系统x120几乎完全相同。

char charDec = 126;  
char charHex = 0x7E; 
char charOct = 0176;
char charBin =  0b01111110;

(标准C不支持像0b01111110这样的二进制常量;这是gcc扩展名。)

当编译器看到像126这样的整数常量时,它会从中计算一个整数值。为此,需要知道126是十进制数字,以及它们的值。

char charSymbol = '~';

为此,编译器只需要识别~是有效字符。

编译器从文本文件C源中读取所有这些字符。该文件中的每个字符都存储为8位序列,表示0到255之间的数字。

因此,如果您的C源代码包含:

putchar('~');

(并且~恰好具有值126),然后编译器需要知道的是126是有效字符值。它会生成将值126发送到putchar()函数的代码。在运行时,putchar将该值发送到标准输出流。如果标准输出转到文件,则值126将存储在该文件中。如果它要去终端,终端软件会进行某种查找,将数字126映射到显示为代字符字符的字形。

编译器必须识别特定的字符值。他们必须认识到+是加号字符,用于表示加法运算符。但是对于输入和输出,不需要ASCII映射,因为每个ASCII字符在处理的所有阶段(从编译到执行)都表示为数字。

那么编译器如何识别'+'字符? C编译器通常用C编写。在编译器自己的源代码中,可能有类似的东西:

switch (c) {
    ...
    case '+':
        /* code to handle + character */
    ...
}

因此编译器在其输入中识别+,因为它自己的源代码中有+ - 并且+(在编译器源代码中存储为8位数字) 43)导致数字43存储在编译器自己的可执行机器代码中。

显然第一个C编译器不是用C编写的,因为没有任何东西可以编译它。早期的C编译器可能用B,BCPL或汇编语言编写 - 每个编译器都由编译器或汇编器处理,可能识别+,因为它自己的源代码中有+码。每一代C编译器都将+的“知识”传递给它编译的下一个C编译器。 +为43的“知识”不一定写在源代码中;每次使用旧编译器编译新编译器时都会传播它。

有关此问题的讨论,请参阅Ken Thompson的文章"Reflections on Trusting Trust"

另一方面,您也可以使用在基于ASCII的系统上运行的编译器,该系统为基于EBCDIC的系统生成代码,反之亦然。这样的编译器必须具有从一个字符集到另一个字符集的查找表映射。

答案 2 :(得分:1)

C语言的类型安全性非常弱,这就是为什么你总是可以为字符变量赋一个整数。

您使用了整数的不同表示来分配给字符变量 - 这在C编程语言中是受支持的。

当您在C程序的文本文件中键入“〜”时,文本编辑器实际上转换了键击并存储了其ASCII等效项。因此,当编译器解析C代码时,它没有感觉到写的是〜(代字号)。在解析时,当编译器遇到等价于'(即单引号)的ASCII时,它进入一种模式以读取下一个字节,作为适合char变量后跟另一个'(单引号)的内容。由于char变量可以具有0-255个不同的值,因此它涵盖整个ASCII集,包括扩展字符集。

使用汇编程序时也是如此。

在完全不同的游戏中打印到屏幕 - 这是I / O系统的一部分。 当您键入键盘上的特定字符时,映射整数的脉冲进入并在读取程序的内存中稳定。同样,当您在打印机或屏幕上打印特定的整数时,该整数将采用相应字符的形状。

因此,如果要在int变量中打印整数,则有一些例程可以转换每个数字并为每个数字发送ASCII代码,I / O系统会将它们转换为字符。

答案 3 :(得分:0)

所有这些值彼此完全相同 - 它们只是相同值的不同表示,因此编译器在将您的书写文本转换为字节值后,以完全相同的方式查看它们。