c语言格式输出剖析——用%d输出float类型数据与int类型%f格式输出

13 篇文章 1 订阅
订阅专栏
5 篇文章 0 订阅
订阅专栏

C语言学习实践

 

摘要

    本文将从C语言变量的本质,不同类型变量在内存中的存储方式,类型强制转换,格式输出4个方面阐述C语言初学阶段的一些问题。

关键词:内存存储,类型强制转换,反汇编

1. 变量

    变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念。在诸如C语言等高级语言中,变量的使用屏蔽了数据的底层细节,使得高级语言程序员不必像汇编程序员那样关心数据与硬件之间的关系。为了探究C语言中变量在内存中的存储形式,可以借助反汇编查看汇编语言以及内存数据。

2. 变量在内存中的存储形式

    在内存中,无论哪种数据类型的数据,都是以相应长度的二进制码存取。从内存取数据是,如果不按照定义数据类型的方式取数据,所取数据就会错误。

2.1   用反汇编查看变量内存数据

(1)   实验代码如下。在赋值部分打点后调试,转入反汇编。

 


(2)   在监视窗口查看变量的内存地址,并在内存窗口中查看数据。


    整形变量_4ByteData的数据在以内存地址0x0023FA58起始的四个Byte中存放:【注意】 Intel处理器是小端机,数据高位在高地址,地位在地址。所存数据:4Bytes的十六进制数 0x12345678

 

    单精度浮点型变量fl的数据在内存中的存储:


    双精度浮点型变量df的数据在内存中的存储:

 

    字符型变量ch的数据在内存中存储;

 

结论:

    (1)   局部变量存储在函数栈中,且该栈向低地址生长,所以先定义的局部变

量在较高内存地址(比如_4ByteData在0x0023FA58,ch在0x0023FA33),并且局部变量之间并非紧密排布,而是由8个Byte 的cc数据隔开。变量周围塞些CCCCCCCC,这可能是编译器提供的一种保护机制,越界了好出断言。通过网上查找资料,这是VC在Debug时给变量留出空间,用来检查stack overflow。

    用release调试,就不会有多余的cc。(但是注意这里char型变量与之前的局部变量之间仍有数据,我猜测这里是应为有变量对齐的缘故,char型变量也占了4byte,只不过多余的3byte由其他数据填充。)

 

    (2)   通过观察不同类型的变量在内存中的存储情况,可以发现:

在32位机器,VS2010 IDE中,一个int型数据占4B,float型变量占4B,double型变量占8B,char型占1B。

2.2    IEEE754 单精度数的格式

单精度浮点数占据4个字节,4个字节的分配如下:

(a)第一位为符号位,0表示正,1表示负;

(b)第2~9位为阶码,采用移码表示;

(c)第10~32位为尾数,采用原码表示。

    给定32位串,如何转换成十进制数:

    假设内存中存在32位串:00 00 00 3f,因为INTELCPU采用little endian存储方式,所以其真实的值为:

0x 3f 00 00 00。将其写成二进制形式:

    (1)第一步,化为二进制

    0 01111110 0000000 00000000 00000000

    (2)第二步

    该浮点数为正数,阶码 01111110,移码表示(126-127) = -1

    尾数 0000000 00000000 00000000

    因为在IEEE754中,单精度浮点数有规格化处理,所以其真正尾数部分为

    1.0000000 00000000 00000000,其中‘.’为小数点

(3)   第三步

    根据公式写出实际数值大小

    0.10000000 00000000 0000000 化为二进制:0.5

2.3    IEEE754 双精度数的格式

    长实数也称双精度数符号位1位,阶码11位,尾数52位

    给定32位串,如何转换成十进制数:

    假设内存中存在64位串:00 00 00 0000 00 e0 3f,因为INTEL CPU采用littleendian存储方式,所以其真实的值为:       0x 3f e0 00 00 00 00 00 00。将其写成二进制形式:

(1)第一步

    0 01111111110 0000 00000000 00000000 00000000 00000000 0000000000000000

(2)第二步

    该浮点数为正数,阶码 01111111110,移码表示(1022-1023) = -1 尾数 0

    因为在IEEE754中,单精度浮点数有规格化处理,所以其真正尾数部分为

    1.0,其中‘.’为小数点

(3) 第三步

    根据公式写出实际数值大小

    0.10 化为二进制:0.5


3. 格式化输出

3.1 printf函数调用的一般形式

    printf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中。但作为一个特例,不要求在使用 printf 函数之前必须包含stdio.h文件。printf函数调用的一般形式为:printf(“格式控制字符串”, 输出表列)。

    其中格式控制字符串用于指定输出格式。格式控制串可由格式字符串和非格式字符串两种组成。格式字符串是以%开头的字符串,在%后面跟有各种格式字符,以说明输出数据的类型、形式、长度、小数位数等。如:

    “%d”表示按十进制整型输出;

    “%ld”表示按十进制长整型输出;

    “%c”表示按字符型输出等

    非格式字符串原样输出,在显示中起提示作用。输出表列中给出了各个输出项,要求格式字符串和各输出项在数量和类型上应该一一对应

3.2 类型不对应下的格式输出

_4ByteData = 0x12345678;  //Hexadecimal:0x12345678 对应Decimal:305419896

    fl = 0.5;

    df = 0.5;

    ch = 65;

    printf("%d\n",_4ByteData);

    printf("%c\n",_4ByteData);

    printf("%d\n",ch);

    printf("%f\n",&_4ByteData);

    printf("%d\n",fl);

    printf("%d\n",df);


分析:

   可以看到同样是int型变量,printf("%d\n",_4ByteData);与

printf("%c\n",_4ByteData);其结果分别为305419896(0x12345678对应的十进制数),而后者只取了4字节数据的最低一个字节0x78,所以打印出了AISII码0x78对应的字符’x’。

   联系C语言中指针的用法,我做出假设:格式输出函数printf()根据类型字符%以及变量名,就可以根据数据首地址+读取长度的方式输出数据。

进一步发现:

    但是对字符型变量ch使用类型字符%d输出,得到的是其ASCII码的十进制数,如果按照上述假设,会输出以ch地址起始的4B的数据(这将是一个错误数据)。

但实验结果是正确输出了ch字符的ACSII码的十进制数。

再对浮点数做实验:

    用类型字符%d输出单精度数,双精度数,结果均为0。

    由上文2.1可知单精度浮点变量fl(十进制0.5)在内存中占4B,机器码是

0x00 00 00 3f(小端机)。现对整数_4ByteData赋值0x3f000000,并使用类型字符%f对该整数输出,查看结果:


 

    结果仍是0。这说明即使内存中数据存储的内容一样,但是使用类型字符%f对整型变量输出,其结果仍然不是浮点数!

    综上,原假设值得怀疑!

4. printf()函数类型不对应下的格式输出进一步研究 

4.1用%d输出float类型数据

    float fl=0.5;如果用printf("%d",fl);输出的是0。 但float型用%d输出是否一定是0呢,答案肯定不都是0(如下图)。

 

为什么 0.5 用%d输出的是0?

分析如下:

    首先来了解下printf的输出格式,int 和 long int 都是32位的,用%d输出;float 、double都是%f输出,但 float 是32位的,double 是64位的,所以在参数传递的时候C语言统一将 float 类型数值传换为double 类型再传入 printf 函数。如果是32位整型则输出格式为%lld。

下面来讲一下  float fl=0.5f ;printf("%d",fl)输出为0的情况:

     %d只输出低32位的数据,并将这些32位二进制以十进制数输出,编译器首先将 0.5从float类型转换为double类型,0.5在内存中的存放方式是0x3f000000,转换成double类型在内存中的数据就是这个0x3fe0000000000000,这个内存数据可以很明显看出低32位全是0,而%d则只能截取到低32位,所以这个以%d输出0.5的数值当然是 0了。如大家不相信可以用%lld 输出看看,这个%lld就很读到低64位数据,读出的结果就是0x3fe0000000000000,在屏幕上看到一个很大的十进制数。(这里用%llx显示十六进制数更直观)


如果我一定要输出0.5在内存中的存放方法怎么办呢?

    可以用printf("%d",*(int *)&fl);这里做了一下处理,不是直接把fl传进来,把fl所在地址里的内容处理了一下,不管fl是什么类型,只对地址进行操作,利用(int *)&lf,将fl所在地址中的内容0x3f000000直接当成 int 类型传给printf,int 的类型数据不会再转成double类型了,所以输出正常,这个只是针对浮点型数据只占低32位,如果输出64位还得用%lld格式控制输出。

如果用printf("%d",(int)fl),输出行不行?

    这个强制类型转换只针对fl的数据类型进行转换,0.5转换 int 类型是0,而上面的*(int *)&a,是对内存中的实际存储数据进行操作,蔽开数据类型这一层面,只将这个数据0x3f000000直接转成int类型输出。而(int)fl,要先看fl的类型,C语言会根据所要数据类型,对内存存储的数据进行改变,以便可以用int类型正确解析内存数据。

    如果用printf("%d",(float)fl),输出什么,输出的是0,这个只是将fl的float类型还转成float类型,还是要自动转成doube类型,传给printf函数。

为什么float非要转成double类型呢?

    因为printf格式控制浮点型输出只有%f,所以统一按doube类型输出,不像整型有32位的%d或%ld,64位的有%lld,这就将32位整型和64位整型用不同的格式控制分开了,而%f则没有,所以printf输出的浮点数其实是统一遍历了64位内存,如果float传入printf没有进行转换,那么printf输出高32位数据将不可预知,printf输出结果也就不正确了,因此传入printf的浮点数都会被编译器隐含转成double类型。


4.2 int类型%f格式输出

如果定义了inta=0x3f000000;用printf("%f",a)输出的结果是多少呢?

   答案是0,至少我们看的屏幕上显示的是0.000000,实际值可不是0啊,只是我们显示的精度只能有15位小数,而实际的数据可能很小很小,0.0000....000几百个0后会有几个有效数据。

我们分析一下:

    首先C语言把a传进printf,因为a是整型,所以不会自动转成double型数据,直接将0x3f0000000传进printf,而%f寻的是64位内存,也就是把0x000000003f000000这个内存中的数据当成浮点型输出来,那浮点型的数据是多少呢,又是怎么存储的呢?

64位浮点数的存放方式:

        63位                 62~52位                 51~0位

        1个符号位       11个阶数                 52个尾数

        从0x000000003f000000来看:

       00000000

        1)符号位是0,表示正

        2)阶数是0,用移码表示:0-1023 = -1023,

用指数表示:1.#*2^-1023,‘#’是代表尾数。

        3)尾数就是,0x000003f000000

        4)浮点二进制表示

 1.000000000000000000000011 1111 000000000000000000000000*2^(-1023),2^-1023次方可想而知有多小!

    这就是为什么我们的int型数据用%f输出是0.000000的原因!

    如果把0.5的双精度数对应的十六进制数赋给long long类型变量,则可以输出正确的小数:

 

5. 总结:

    通过以上实验,我验证了原假设基本正确

    格式输出函数printf()根据类型字符%以及变量名,就可以根据数据首地址+读取长度的方式输出数据。

但是,还要注意其中的一些细节:

(1)用%d输出float类型数据时,在参数传递的时候C语言统一将 float 类型数值传换为 double 类型再传入 printf 函数。而%d只截取低32位数据,所以得到的数字不是相应浮点数的二进制码。

 

(2)int类型%f格式输出,%f寻的是64位内存,所以输出的数据可能很小(比如2^-1023),那么结果是0.

 

    综上,无论什么类型的数据,都只是01二进制数据。只要清楚其内存存储机制,拿到数据首址+偏移量,就能正确操作该数据!

    最后,我想说C语言非常灵活,高级程序员也要熟悉汇编语言,会使用反汇编这把“手术刀”在底层剖析程序,会有更深刻的认识!

c语言 float输出对齐,c语言格式输出剖析——用%d输出float类型数据int类型%f格式输出...
weixin_42513054的博客
05-19 2464
C语言学习实践摘要本文将从C语言变量的本质,不同类型变量内存中的存储方式,类型强制转换,格式输出4个方面阐述C语言初学阶段的一些问题。关键词:内存存储类型强制转换,反汇编1. 变量变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念。在诸如C语言等高级语言中,变量的使用屏蔽了数据的底层细节,使得高级语言程序员不必像汇编程序员那样关心数据与硬件之间的关系。为了探究C语言变量内存中的...
EDA/PLD中的C语言中结构体与联合体的简单用法
11-08
摘要:本文简要分析结构体、联合体2种特殊的数据类型,结合链表和结构体的综合运用,详细注释创建链表的计算机执行和处理的过程,并对一些概念结合代码举例分析,指出常见错误和问题。 结构体 结构体是一种特殊的...
C语言的指针类型详细解析
01-20
指针存储内存的地址,同时指针是有类型的,如int*,float*,那么,一个自然的猜想就是指针变量应该存储这两方面的信息:地址和指针类型,比如,就像下面的结构体: 代码如下:struct pointer{    long address;    int type;}举个例子:打印sizeof(int*),值为4,可见4字节是存储内存地址用的,反过来就说明指针并没有存储类型信息的地方,那么指针的类型信息存放在哪儿呢?下面剖析一段简单的代码。 代码如下:// ma.cpp : 定义控制台应用程序的入口点。#include “stdafx.h”char gi;char *pi; void main
C语言程序设计实验报告——实验.doc
03-09
C语言程序设计 "实"1.掌握结构体类型的概念和说明方法 " "验"2.掌握结构体变量的定义和引用。结构体类型变量成员的使用。 " "目"3.掌握结构体数组的定义和使用方法。 " "的"4.掌握指向结构体变量的指针变量的概念和应用。 " " "5.掌握结构变量与指向结构的指针作为函数参数实现函数的调用。 " " "6.掌握共用体的概念和说明方法。 " " "7.掌握共用体变量的定义和引用。共用体类型变量成员的使用 " " "8.掌握位运算的概念和方法。 " " "9.掌握位运算符(&,", ,~)的使用方法。 " " "10.了解有关位运算的算法。 " " "11.掌握枚举类型概念和说明方法 " " "12.掌握枚举类型变量的定义以及枚举类型变量的使用。 " " "1.建立一个学生的简单信息表,其中包括学号、年龄" " " "、性别及一门课的成绩。要求从键 " " " "盘输入数据,并显示出来。上机运行以下程序。 " " " "分析:一个学生信息表可以由结构体来定义,表中的 " " " "内容可以通过结构体中的成员来 " " " "表示。体会结构体成员的点运算符引用方法。 " " " "#include"stdio.h" " " "实"void main() " " " "{ " " "验"struct st " " " "{ " " "内"int num; " " " "int age; " " "容"char sex; " " " "float score; " " "与"}; " " " "struct st info; " " "步"printf("input number:"); " " " "scanf("%d",&info.num); " " "骤"printf("input age:"); " " " "scanf("%d",&info.age); " " " "getchar(); " " " "printf("input sex:"); " " " "scanf("%c",&info.sex); " " " "printf("input score:"); " " " "scanf("%f",&info.score); " " " "printf("number=%d\n",info.num); " " " "printf("age=%d\n",info.age); " " " "printf("sex=%c\n",info.sex); " " " "printf("score=%f\n",info.score); " " " "} " " " "2.建立 5 " " " "名学生的信息表,每个学生的数据包括学号、姓名及 " " " "一门课的成绩。要求从键盘 " " " "输入这 5 名学生的信息,并按照每一行显示一名学 " " " "生信息的形式将 5 名学生的信息显示出 " " " "来。上机运行以下程序。 " " " "分析:每个学生的数据学号、姓名及一门课的成绩用 " " " "结构体表示,5 名学生的信息表 " " " "用结构体数组表示,体会结构体数组元素的引用方法 " " " "。 " " " "#include"stdio.h" " " " "#define N 5 " " " "struct stud " " " "{ " " " "int num; " " " "char name [20]; " " "实"float score; " " " "}; " " "验"struct stud s[N]; " " " "void main() " " "内"{ " " " "int i; " " "容"for (i=0;i<N;i++) " " " "{ " " "与"printf("input number:"); " " " "scanf("%d",&s[i].num); " " "步"printf("input name:"); " " " "scanf("%s",s[i].name); " " "骤"printf("input score:"); " " " "scanf("%f",&s[i].score); " " " "} " " " "for (i=0;i<N;i++) " " " "{ " " " "printf("%d ",s[i].num); " " " "printf("%s ",s[i].name); " " " "printf("%f\n",s[i].score); " " " "} " " " "} " " " "3.显示某人工资信息的程序如下,分析显示结果。上 " " " "机运行以下程序。 " " " "分析:某人工资信息可以由结构体来定义,表中的内 " "
顺序结构程序设计
最新发布
2402_84250824的博客
04-22 614
顺序结构程序设计基本概要
c语言读取obj文件转换数据的小例子
12-26
代码如下:// hello.cpp : Defines the entry point for the console application.// #include “stdafx.h”#include “stdio.h” int _tmain(int argc, _TCHAR* argv[]){    FILE *file1,*file2;    file1=fopen(“047facesmall.obj”,”r”); //读文件    file2=fopen(“047.obj”,”w+”);  //保存的文件    float a,b,c;    int e,f,g;    char v
C语言中结构体与联合体的简单用法
01-19
摘要:本文简要分析结构体、联合体2种特殊的数据类型,结合链表和结构体的综合运用,详细注释创建链表的计算机执行和处理的过程,并对一些概念结合代码举例分析,指出常见错误和问题。  结构体  结构体是一种特殊的数据类型,它可以将很多数据类型打包,然后只要操作该结构体的指针变量便可以轻松的访问该结构体内其他的数据。举例如下: struct student { char name[8]; int age; char depart[20]; float grade; }freshman ;   student是结构名,大括号内为该结构体打包的数据类型。如果定义 struct student
深入分析C语言中结构体指针的定义与引用详解
12-31
指向结构体类型变量的使用首先让我们定义结构体:struct stu{char name[20];long number;float score[4];} ;再定义指向结构体类型变量的指针变量:struct stu *p1, *p2 ;定义指针变量p 1、p 2,分别指向结构体类型变量。引用形式为:指针变量→成员;[例7-2] 对指向结构体类型变量的正确使用。输入一个结构体类型变量的成员,并输出。 代码如下:#include <stdlib> /*使用m a l l o c ( ) 需要* /struct data / *定义结构体* /{int day,month,year;} ;stru
%d输出float类型,%f输出int类型
Markdown
05-14 3748
// 输出格式类型不一致,输出结果实际上与存储有关 // 1.int以%f格式输出,结果一般为0.000000 // 2.long long 类型的很大的数,用printf(“%f”)打印出来可能为一个小数; // 3.double、float以%d格式输出(输出时,float会转化为double存储形式;%d取低32位) // (1)结果一般为绝对值很大的数(当浮点数不能精确表示时,低32位不为0) //
c语言格式输入输出:%d %f
weixin_50539337的博客
01-05 681
%d 整型输出 %ld长整型输出 %c 输出字符 %s输出一个字符串 %f输出实数,以小数形式输出 %o 以八进制数形式输出整数 %x 以十六进制数形式输出整数 %u 以十进制形式输出unsigned型数据(无符号) %e以指数形式输出实数 %g根据大小自动选择f格式或者e格式,并且不输出无意义的零。 ...
2. 区分数据类型double和float格式控制符%f与%lf
lxw的博客
04-18 1787
区分数据类型double和float格式控制符%f与%lf
C语言编程题(三)整型和浮点型混合运算
qq_51519091的博客
09-14 1066
对于小数部分,我们需要进行乘2取整的操作。具体步骤如下: 0.25 * 2 = 0.5 整数部分为0 0.5 * 2 = 1.0 整数部分为1。首先,将165.25转换为二进制表示形式。整数部分的转换是简单的,可以直接转换为二进制数字:165转换为二进制是10100101。最高位是符号位(S):0表示正数,1表示负数。接下来的8位是指数位(E)。剩下的23位是尾数位(M)。将整数部分和小数部分的二进制放在一起,得到:10100101.01。将乘法过程得到的整数按顺序排列,得到0.01。
严蔚敏《数据结构(C语言版)习题集》答案
04-14
严蔚敏《数据结构(C语言版)习题集》答案 第一章 绪论 1.16 void print_descending(int x,int y,int z)//按从大到小顺序输出个数 { scanf("%d,%d,%d",&x,&y,&z); if(x) x<->y; //为表示交换的双目运算符,以下...
C语言常见几中图形打印代码
10-28
现已经历过几个步骤:从简单的了解操作平台Xcode开始,到熟悉基本的数据类型:整型:int、long、short;字符型:char;实型:float、double。然后接触到编程语言的分支结构分类——顺序、分支、循环。其中循环是重点...
华中科技大学 编译原理 面向过程的C语言的编译器设计 含有词法分析和语法分析、语义分析、中间代码生成的 源码.zip
02-07
源语言要求至少包含的语言成分如下: 数据类型至少包括char类型int类型float类型 基本运算至少包括算术运算、比较运算、自增自减运算和复合赋值运算 控制语句至少包括if语句和while语句 实验内容:完整可运行的...
C语言程序设计-程序举例求矩阵之和.pptx
07-05
C语言程序设计 ——数组 程序举例-求矩阵之和 4-3 程序举例-求矩阵之和 任务需求 求一个3×3矩阵对角线元素之和 。 任务分析 利用双重for循环控制输入二维数组,再将a[i][i]累加后输出。 示例代码 main() { float a...
Object-C中的格式说明符
七彩祥云至尊宝
07-18 3122
%@:             Objective-C对象,印有字符串返回descriptionWithLocale:如果于的话,或描述相反.CFTypeRef工作对象,返回的结果的CFCopyDescription功能.(这个翻译有问题建议按照自己的理解方式理解)。 %%:             为'%'字符; %d,%D,%i:   为32位整型数(int); %u,%U:
C语言中printf用%d输出float类型数据,或以%f输出int数据的结果
热门推荐
Do
07-15 3万+
C语言中printf用%d输出float类型数据,或以%f输出int数据的结果 IEEE754标准 单精度(32位)/双精度(64位)浮点数解码 float double 有效位数
C语言实现词法分析器,包含输入输出的例子
03-20
以下是一个简单的用C语言实现的词法分析器的例子: ```c #include <stdio.h> #include <ctype.h> #include <string.h> #define MAX_TOKEN_LEN 100 typedef enum { INT, FLOAT, STRING, IDENTIFIER, KEYWORD, OPERATOR, PUNCTUATOR, END_OF_FILE } TokenType; typedef struct { TokenType type; char value[MAX_TOKEN_LEN]; } Token; char *keywords[] = {"if", "else", "while", "for", "int", "float", "char", "void", "return", NULL}; char *operators[] = {"+", "-", "*", "/", "=", "==", "!=", "<", ">", "<=", ">=", NULL}; char *punctuators[] = {",", ";", "(", ")", "{", "}", "[", "]", NULL}; int is_keyword(char *token) { int i = 0; while (keywords[i] != NULL) { if (strcmp(keywords[i], token) == 0) { return 1; } i++; } return 0; } int is_operator(char *token) { int i = 0; while (operators[i] != NULL) { if (strcmp(operators[i], token) == 0) { return 1; } i++; } return 0; } int is_punctuator(char *token) { int i = 0; while (punctuators[i] != NULL) { if (strcmp(punctuators[i], token) == 0) { return 1; } i++; } return 0; } Token get_token() { Token token; char c = getchar(); while (isspace(c)) { c = getchar(); } if (isdigit(c)) { token.type = INT; int i = 0; while (isdigit(c)) { token.value[i++] = c; c = getchar(); } if (c == '.') { token.type = FLOAT; token.value[i++] = c; c = getchar(); while (isdigit(c)) { token.value[i++] = c; c = getchar(); } } token.value[i] = '\0'; ungetc(c, stdin); } else if (isalpha(c) || c == '_') { token.type = IDENTIFIER; int i = 0; while (isalnum(c) || c == '_') { token.value[i++] = c; c = getchar(); } token.value[i] = '\0'; ungetc(c, stdin); if (is_keyword(token.value)) { token.type = KEYWORD; } } else if (is_operator(&c)) { token.type = OPERATOR; int i = 0; while (is_operator(&c)) { token.value[i++] = c; c = getchar(); } token.value[i] = '\0'; ungetc(c, stdin); } else if (is_punctuator(&c)) { token.type = PUNCTUATOR; int i = 0; while (is_punctuator(&c)) { token.value[i++] = c; c = getchar(); } token.value[i] = '\0'; ungetc(c, stdin); } else if (c == '\"') { token.type = STRING; int i = 0; c = getchar(); while (c != '\"') { token.value[i++] = c; c = getchar(); } token.value[i] = '\0'; } else if (c == EOF) { token.type = END_OF_FILE; } else { token.type = OPERATOR; token.value[0] = c; token.value[1] = '\0'; } return token; } int main() { Token token; do { token = get_token(); switch (token.type) { case INT: printf("INT: %s\n", token.value); break; case FLOAT: printf("FLOAT: %s\n", token.value); break; case STRING: printf("STRING: %s\n", token.value); break; case IDENTIFIER: printf("IDENTIFIER: %s\n", token.value); break; case KEYWORD: printf("KEYWORD: %s\n", token.value); break; case OPERATOR: printf("OPERATOR: %s\n", token.value); break; case PUNCTUATOR: printf("PUNCTUATOR: %s\n", token.value); break; case END_OF_FILE: printf("END OF FILE\n"); break; } } while (token.type != END_OF_FILE); return 0; } ``` 这个词法分析器可以识别整数、浮点数、字符串、标识符、关键字、运算符和标点符号,并将它们分别输出。例如,输入以下代码: ```c int main() { int a = 123; float b = 3.14; char c = 'A'; char *str = "Hello, world!"; if (a > 100) { printf("%s\n", str); } else { printf("%c\n", c); } return 0; } ``` 输出的结果如下: ``` KEYWORD: int IDENTIFIER: main PUNCTUATOR: ( PUNCTUATOR: ) PUNCTUATOR: { KEYWORD: int IDENTIFIER: a OPERATOR: = INT: 123 PUNCTUATOR: ; KEYWORD: float IDENTIFIER: b OPERATOR: = FLOAT: 3.14 PUNCTUATOR: ; KEYWORD: char IDENTIFIER: c OPERATOR: = OPERATOR: ' IDENTIFIER: A OPERATOR: ' PUNCTUATOR: ; KEYWORD: char OPERATOR: * IDENTIFIER: str OPERATOR: = STRING: Hello, world! PUNCTUATOR: ; KEYWORD: if PUNCTUATOR: ( IDENTIFIER: a OPERATOR: > INT: 100 PUNCTUATOR: ) PUNCTUATOR: { IDENTIFIER: printf PUNCTUATOR: ( STRING: %s\n PUNCTUATOR: , IDENTIFIER: str PUNCTUATOR: ) PUNCTUATOR: ; PUNCTUATOR: } KEYWORD: else PUNCTUATOR: { IDENTIFIER: printf PUNCTUATOR: ( STRING: %c\n PUNCTUATOR: , IDENTIFIER: c PUNCTUATOR: ) PUNCTUATOR: ; PUNCTUATOR: } KEYWORD: return INT: 0 PUNCTUATOR: ; PUNCTUATOR: } END OF FILE ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • KITTI数据集简介与使用 248743
  • 归一化函数normalize详解 112870
  • 生成式对抗网络GAN研究进展(一) 50947
  • 用R语言做回归分析_iris数据集/longley数据集 49706
  • 生成式对抗网络GAN研究进展(五)——Deep Convolutional Generative Adversarial Nerworks,DCGAN 41366

分类专栏

  • 机器学习 14篇
  • 机器学习 33篇
  • 学习资料整理 13篇
  • c语言 5篇
  • R语言 3篇
  • OpenCV 9篇
  • 计算机视觉CV 26篇
  • Linux 9篇
  • python 5篇
  • 工具使用 6篇
  • 并行程序设计 6篇
  • 深度学习 33篇
  • Caffe 8篇
  • 物体检测 21篇

最新评论

  • KITTI数据集简介与使用

    极恶狒狒: 能做到测距吗?我目前只能生成灰度深度图片

  • 《机器学习系统设计》之k-近邻分类算法

    zitong_L: 你好,请问这个有完整的代码吗

  • 《机器学习系统设计》之应用scikit-learn做文本分类(下)

    前面听说风很大755: 为什么被提示没有load_mlcomp这个函数

  • KITTI数据集简介与使用

    weixin_38832719: 请问您知道怎么获取激光雷达的数据么,主要是深度信息

  • 典型的色彩空间介绍

    weixin_42489642: 您好,这个CMYK这个公式及计算来源哪里呢

您愿意向朋友推荐“博客详情页”吗?

  • 强烈不推荐
  • 不推荐
  • 一般般
  • 推荐
  • 强烈推荐
提交

最新文章

  • 3.5 YOLO9000: Better,Faster,Stronger(YOLO9000:更好,更快,更强)
  • 3.4 无proposal检测方法(3): SSD: Single Shot MultiBox Detector
  • 3.3 无proposal检测方法(2): G-CNN: an Iterative Grid Based Object Detector
2017年15篇
2016年43篇
2015年27篇
2014年10篇

目录

目录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

4617作文网周易方位高起本怎样报名废旧回收公司起名字大全免费周易培训哪家好八字合婚免费 周易周易可以算命吗周易天干地支五行查询门窗店起什么名字好听适合起名怎么词资产运营公司 起名综合商店起什么名字好适合用来起名的字周公解梦安卓易经周易周易缘国学取名网周易64卦爻辞周易免费取名字网算命的说环保砖厂起名六爻算命准吗起名字尚姓名字用成语送给男孩起名字起名张国什么周易姓名免费打分沈姓起名字大全男孩梦解玄机大全大环保公司起名姓魏起名字好千明周易取名网生辰八字免费周易是谁编的淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻让美丽中国“从细节出发”清明节放假3天调休1天男子给前妻转账 现任妻子起诉要回网友建议重庆地铁不准乘客携带菜筐月嫂回应掌掴婴儿是在赶虫子重庆警方辟谣“男子杀人焚尸”国产伟哥去年销售近13亿新的一天从800个哈欠开始男孩疑遭霸凌 家长讨说法被踢出群高中生被打伤下体休学 邯郸通报男子持台球杆殴打2名女店员被抓19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警两大学生合买彩票中奖一人不认账德国打算提及普京时仅用姓名山西省委原副书记商黎光被逮捕武汉大学樱花即将进入盛花期今日春分张家界的山上“长”满了韩国人?特朗普谈“凯特王妃P图照”王树国3次鞠躬告别西交大师生白宫:哈马斯三号人物被杀代拍被何赛飞拿着魔杖追着打315晚会后胖东来又人满为患了房客欠租失踪 房东直发愁倪萍分享减重40斤方法“重生之我在北大当嫡校长”槽头肉企业被曝光前生意红火手机成瘾是影响睡眠质量重要因素考生莫言也上北大硕士复试名单了妈妈回应孩子在校撞护栏坠楼网友洛杉矶偶遇贾玲呼北高速交通事故已致14人死亡西双版纳热带植物园回应蜉蝣大爆发男孩8年未见母亲被告知被遗忘张立群任西安交通大学校长恒大被罚41.75亿到底怎么缴沈阳一轿车冲入人行道致3死2伤奥运男篮美国塞尔维亚同组周杰伦一审败诉网易国标起草人:淀粉肠是低配版火腿肠外国人感慨凌晨的中国很安全男子被流浪猫绊倒 投喂者赔24万杨倩无缘巴黎奥运男子被猫抓伤后确诊“猫抓病”春分“立蛋”成功率更高?记者:伊万改变了国足氛围奥巴马现身唐宁街 黑色着装引猜测

4617作文网 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化