导航:首页 > 源码编译 > 编译原理布尔判断必须从左往右吗

编译原理布尔判断必须从左往右吗

发布时间:2023-04-23 18:15:38

‘壹’ 编译原理 while 语句文法

while(条件)
{
.......;//语句
X++或者X--;//做自增或自减运算来达到循环的过程
}
while后面跟一堆小括号,里面的条件判断,类似IF语句,当条件满足时做以下语句的循环,条件不满足后直接跳出循环;
例题:
int i=0;//初始化i=0
while(i<5)//i=0满足判断的条件,进入循环语句
{
i++;//做自增运算,当i+到5时跳出循环,因为i不小于5了
}
printf("%d",i);//此时i的值为5

‘贰’ 编译器笔记34-中间代码生成-布尔表达式的回填

基本思想:生成一个跳转指令时,暂时不指定该跳转指令的目标标号。这样的指令都被放入由跳转指令组成的列表中。同一个列表中的所有跳转指令具有相同的目标标号。等到能够确定正确的目标标号时,才去填充这些指令的目标标号。

B.truelist:指向一个包含跳转指令的列表,这些指令最终获得的目标标号就是当B为真时控制流应该转向的指令的标号。

B.falselist:指向一个包含跳转指令的列表,这些指令最终获得的目标标号就是当B为假时控制流应该转向的指令的标号。

为了处理衫芹跳转指令的列表我们构造了三个函数

上述的布尔表达式将被翻译成两条跳转指令。两条跳转指令的标号都不填写因为这两条跳转指令的标号都在等待回填,因此我们要把它放到相应的列表中。

第一条跳转指令的目标标号是B的真出口,因此我们把它放到B.truelist中。调用makelist函数生成一个只包含nextquad的列表,并把这个列表的指针赋值给truelist,这里的nextquad是指即将生成的下一条指令的标号或瞎毕,即gen('if' E1.addr relop E2.addr'goto_')这条指令的标号。

第二条跳转指令的目标标号是B的假出口,因此把这条跳转指令存放到B.falselist中。因此我们调用makelist函数生成一个只包含nextquad+1这样一个标号的列表,nextquad+1标号就是gen('goto_')这条指令的标号。

这样的话我们就将这两条指令分别放入到B.truelist和B.falselist中。

问:list中存的是对应跳转指令的标号?

当B定义为true时,此时可以确定布尔表达式的值为真,生成一条跳转到B的真出口的一条指令。由于此真出口的标号不能确定有待回填,我们把它放入到B.truelist中。

当B定义为false时,此时可以确定布尔表达式的值为假,生成一条跳转到B的假出口的一条指令。由于此真出口的标号不能确定有待回填,我们把它放入到B.falselist中。

对B的翻译与其对应的子表达式B1的翻译是相同的,因此B的属性值等于B1的属性值。

B的值与B1的值正好相反,因此将两个非终结符的属性进行对调。

B1.truelist中的这些指令都要跳转到B1的真出口,当B1为真的时候整个表达式的值就是为真的,因此B1的真出口就是B的真出口。要跳转到B1的真出口就是跳转到B的真出口,因此B1.truelist中的指令都要放到B.truelist中。

B2.truelist的指令都要跳转到真出口,当B2为真时整个表达式的值也为真,因此B2的真出口就是B的真出口。要跳转到B2的真出口就是要跳转到B的真出口,因此B2.truelist中的指令都要放到B.truelist中。

B1.falselist中的指令它们都是要跳转到B1的假出口,当B1的值为假的时候我们要进一步判断B2的值,因此B1的假出口就是B2的第一条指令,因此B1.falselist中的指令都要跳转到B2的第一条指令。

B2.falselist中的指令都要跳转到B2的假出口,当B2的值为假的时候那么整个布尔表达式的值也是假的。因此B2的假出口就是B的假出口,要跳转到B2的假出口也就是要跳转到B的假出口。B2.falselist中的指令都要放置到B.falselist中。

根据此示意神前图可以看出,在分析B2之前,要用B2的第一条指令的标号来回填B1.falselist中的各条指令。当然我们可以记录下B2的第一条指令的标号在归约时完成此回填动作。为了记下B2第一条指令的标号我们在非终结符B2之前插入一个标记非终结符M。与M关联的语义动作它的任务就是记录下B2的第一条语义动作的标号。我们给M设置一个综合属性quad,M.quad等于下一条指令的标号。因为我们把M放在B2之前,因此M.quad记录的是第二条指令的标号。根据翻译方案示意图,我们要用M.quad来回填B1.falselist中的各条指令,因此调用backpatch用M.quad回填B1.falselist中的各条属性。B.truelist是由B1.truelist和B2.truelist合并而成的,因此我们调用merge函数将B1.truelist和B2.truelist进行合并,将合并后的指针赋值给B.truelist。

注:因为这里我们定义的都是综合属性,从左向右扫描输入串。makelist函数生成一个只包含下一条指令的列表,并把指针赋值给B.trulist。我们假设下一条指令从100开始。gen(‘if ’ E 1 .addr relop E 2 .addr ‘goto _’)中E1.address等于a,relop就是小于号,E2.address等于b,引号中的字符串按字面值传递。下划线表示待回填的目标标号。

注:将栈顶中的空串归约成一个标记非终结符M

注:有四条指令是等待回填的,在B的truelist中有两条指令100和104,当B的真出口确定以后我们将用B的真出口的标号这两条指令。同理当B的假出口确定以后将会用B的假出口的标号回填此两条指令。

‘叁’ 含有默认参数的函数对其参数赋值时必须是从左至右吗

这个说法有点问题吧?定义时,函数的默认形参必须运喊放在非默认形参的右边,但“赋值”应该是指将实参的值对应拷贝给形参的过程,这个过程是从右至左进败扰行的。旁枯野比如若有函数void f(int a,int b,int c,int d=3,int e=0);,假设这样调用:int x=7;f(5,x,x+=1);,那么函数中得到的是a==5,b==8,c==8,d==3,e==0。看代码与结果:

‘肆’ C语言布尔头文件使用方法

1、ANSI C99标准规定C语言中有布尔类型(_Bool)。为了方便,使用布尔类型可以加入头文件stdbool.h,该文件定义了bool=_Bool,true=1,false=0。使用布尔类型必须保证所使用的编译器支持C99标准。

2、C语言的逻辑判断只是判断0或非0,只要能保存整型数据的变量类型都可以作为布尔型使用。 用特殊色彩标记关键字的功能是编辑器的功能而非编译器的功能,因为C++有bool类型,因此bool会被编辑器标亮,但是C语言编译隐轮隐器是不会认识这个关桐链键字的。灶厅
C语言中bool可以自定义,例如:
#define bool int
#define false 0
#define true 1

‘伍’ c需要 a+=6=a 怎么理解

正常理解是从右往左看悔仿,先碧弊纤判断6 = a的布卜滚尔值,然后再自加到a。
但是我在GCC的C11标准下编译没有通过。

‘陆’ 布尔运算符的短路判断的规则是什么

预绝肆旦编译处理,对于双&&或双||都是先判断符号左边的表达式为什么,再决定是否要去判断右边的表达式(即执行),例如: 有int变量x=1,y=1,下面的代并扰码:if(x==1&&++y==3),尽管右边的是错误的,最后结果也是真,并且没有执行++y这个操作,即执行完代码后雹蚂y的值依然为1,同理||也是如此,不同在于当左边为假才短路。

‘柒’ C语言中,如何定义一个布尔型变量

C语言中并没有bool类型变量。这是C++中新增的系统类型。
要在C语言中使用bool类型,可以使用自简猛定义的方式。
1 使吵咐手用整型做bool类型。
typedef int bool;

typedef unsigned char bool;
只要是整型,都可以当做bool使用。
2 使用枚举类型做bool类升嫌型。
typedef enum
{
false,

true

}bool;
实际应用中,枚举类型较为普遍。

‘捌’ 请问C语言中 *x++ (*x)++ ++*x *++x的区别

先比较++和*(指针)的优先级,++较高。

那么*x++就是取x指向内存的值,然后x+=1;

(*x)++是x指向内存的值,然后其内存的值自增1。

++*x 是x指向内存的值先自增1,在取该值。

*++x 是x先+=1,在取其指向内存的值。

++跟*的优先级一样,两个若一起出现,运算顺序是从右往左(不是常规的从左往右),所以++*x即++(*x)是先取x的值,然后让值自己加1;(地址没变,指针指向的值变了。)

*++x即*(++x),先让x的自己加1,就是x的地址加上这个指针类型的步长(比如说这个指针是int类型,那它的地址+4,),然后再取x的值。(地址变了,但是值没变)

(8)编译原理布尔判断必须从左往右吗扩展阅读:

基本数据类型

void:声明函数无返回值或无参数,声明无类型指针,显示丢弃运指袜蚂算结果。(C89标准新增)

char:字符型类型数据,属于整型数据的一种。(K&R时好滚期引入)

int:整型唯埋数据,表示范围通常为编译器指定的内存字节长。(K&R时期引入)

float:单精度浮点型数据,属于浮点数据的一种。(K&R时期引入)

double:双精度浮点型数据,属于浮点数据的一种。(K&R时期引入)

Bool:布尔型(C99标准新增)

Complex:复数的基本类型(C99标准新增)

Imaginary:虚数,与复数基本类型相似,没有实部的纯虚数(C99标准新增)

Generic:提供重载的接口入口(C11标准新增)

类型修饰关键字

short:修饰int,短整型数据,可省略被修饰的int。(K&R时期引入)

long:修饰int,长整型数据,可省略被修饰的int。(K&R时期引入)

long long:修饰int,超长整型数据,可省略被修饰的int。(C99标准新增)

signed:修饰整型数据,有符号数据类型。(C89标准新增)

unsigned:修饰整型数据,无符号数据类型。(K&R时期引入)

restrict:用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式。

‘玖’ 用C++实现布尔表达式的真值问题

#include <stdio.h>

#include <string.h>


bool eval(const char*s){ if(!s) return 0;

if(*s==0 || *s==')') return 0;


if(*s=='(') return eval(s+1);


const char*p=s;

char c=*p++; if(c!='T' && c!='F') printf("Invalid expression. "); return 0;

bool v=(c=='T')?1:0;


if(*p=='!') v!=eval(p+1);

else if(*p=='|') v|=eval(p+1);

else if(*p=='&')v&=eval(p+1);

else if(*p!=0 && *p!=')')printf("Invalid expression... ");


return v;

}


int main(){

char*s="(T|T)&F&(F|T)";


printf("eval( %s )=%c Press Enter to quit... ", s, (eval(s)==0)?'F':'T');

getchar();

return 0;

}


‘拾’ 编程学习

Java语言适合初学者学习,
Java语言由语法规则和类库两部分组成,其中语法规则确定了Java程序的书写规范,学习好语法规则是Java语言,也是所有编程语言的基本功。本文主要向大家简单介绍一下Java的语法规则。 Java语言与C/C++语言有着紧密的联系,Java中的许多术语来自于C++,起语法也来自于C++。因此Java的语法和c++的语法计划一模一样。下面简单介绍一下Java的具体语法。

一、Java的词法
1、标识符
标识符是类、变量和方法等的名字,作用是让编译器能够识别它们。在Java语言中,标识符可以包含数字、字母、下划线(_)和美圆符号($),但是不能以数字作为开头。与C/C++语言不同的是,Java语言还可以将一些非拉丁字母包含在标识符中,这是因为Java语言使用的是Unicode字符,所有的十六进制00C0以上的Unicode字符都可以用在标识符中。但是Java语言的关键字是不能用来作为标识符的。

我们在使用标识符的时候应该尽量表达所要表示的类、变量、方法等的含义。另外,标识符中可以使用下划线,我们应该充分利用这一点以提高程序的可读性。

2、关键字

以下是Java的全部关键字:
abstract double int strictfp**
boolean else interface super
break extends long switch
byte final native synchronized
case finally new this
catch float package throw
char for private throws
class goto* protected transient
const* if public try
continue implements return void
default import short volatile
do instanceof static while
* 尚未使用的关键字
** 为Java 2增加的关键字

3、注释

Java有三种形式的注释:

第一种是C语言的传统注释方式,即将“/*”和“*/”之间的文本都视为注释,这种注释可以跨越多行。

第二种是C++风格的注释,即将“//”之后直到行尾的文本都视为注释,这种注释只能包含一行。

第三种是Java新增加的注释方式,即将“/**”和“*/”之间的文本都视为注释,这种注释也可以夸耀多行。注意,这种注释方式生成的注释将作为Javadoc文档保存。

二、操作符
1、算术操作符

操作符 用途 优先级 结合性
++,-- 自动递增,自动递减 2(仅次于括号) 从右到左
+,- 一元加,一元减 2 从右到左
*,/ 乘,除 3 从左到右
% 取余(求模) 3 从左到右
+,- 加,减 4 从左到右

2、布尔运算与关系运算符
操作符 用途 优先级 结合性
>,<,>=,<= 测试相对大小 6 从左到右
== 测试相等性 7 从左到右
!= 测试不等性 7 从左到右
?: 根据第一个操作数返回后两个操作数之一 13 从左到右
! 非 2 从右到左
& 布尔与 8 从左到右
^ 异或 9 从左到右
| 布尔或 10 从左到右
&& 条件与 11 从左到右
|| 条件或 12 从左到右

3、位操作符
操作符 用途 优先级 结合性
~ 非(位求补) 2 从右到左
<<,>> 左移,右移 5 从左到右
>>> 当作无符号右移 5 从左到右
& 位和 8 从左到右
^ 位异或 9 从左到右
| 位或 10 从左到右

4、赋值操作符
操作符 用途 优先级 结合性
= 赋值 14 从右到左
*= 操作同时赋值 14 从右到左
/= 操作同时赋值 14 从右到左
%= 操作同时赋值 14 从右到左
+= 操作同时赋值 14 从右到左
-= 操作同时赋值 14 从右到左
>>= 操作同时赋值 14 从右到左
<<= 操作同时赋值 14 从右到左
>>>= 操作同时赋值 14 从右到左
^= 操作同时赋值 14 从右到左
|= 操作同时赋值 14 从右到左
&= 操作同时赋值 14 从右到左

5、特殊操作符
cast操作符将一种数据类型转换成为另一种数据类型,cast应写成把要校正操作数的类型名放在括号中。

例如: int i; long l; l=7876547; i=(int)l; 如果给高精度的变量赋予一个低精度值,则不需校正。类型校正操作符的优先级为2,结合性为从右到左结合。

将以上讲到的操作符的优先级总结如下:

优先级 运算符 结合顺序
1 []数组运算 .点运算符 ()调用方法 从左到右
2 ! ~ ++ -- +(一元加) -(一元减) ()强制类型转换 new 从右到左
3 * / % 从左到右
4 +(二元加) -(二元减) 从左到右
5 >> << >>> 从左到右
6 < <= > >= instanceof 从左到右
7 == != 从左到右
8 & 从左到右
9 ^ 从左到右
10 | 从左到右
11 && 从左到右
12 || 从左到右
13 ?: 从左到右
14 = += -= *= /= %= &= |= ^= <<= >>= >>>= 从右到左

三、常量
1、整型常量

在Java语言中,整型常量有三种形式,它们分别是:十进制、八进制、十六进制。
需要注意的是十进制数不能以0开头,这是因为八进制的数是以0开头的,而十六进制数以0x或0X开头。

2、浮点型常量

浮点数只能表示十进制数。浮点数有两种表示方法,即标准表示法和科学记数法。浮点数又分为单精度数和双精度数。

3、布尔型常量

布尔型常量有两个值:ture(或TURE)和false(或FALSE)它们分别表示真和假,这两个值用来表示事物的状态,它们必居其一。通过测量布尔值可以判断是否执行某个步骤。

4、字符型常量

字符型常量是一个单一的字符,其形式是由两个单引号引起来的一个字符。但是两个单引号引起来的不能是单引号和反斜杠,即‘’和‘\’是不正确的写法。

大家一定要记住,Java语言中的字符是16位的Unicode字符,这与C/C++等语言是不一样的。

同C/C++语言一样,Java语言也有转意序列。Java中的转意序列的功能见下表:

转义序列 标准形式 功能描述
\ 继续
\n NL 回车换行
\t HT 水平制表符
\b BS 后退一格
\r CR 回车不换行
\f FF 换页
\ 单引号
\\ \ 反斜杠
\" " 双引号
\ddd 0ddd 八进制模式
\xddd 0xddd 十六进制模式
\udddd 0xdddd Unicode双字节字符

字符串常量
字符串常量是由双引号引起来的一系列字符,与C/C++语言中不同的是,Java语言中的字符串不是通过字符数组来实现的,而是通过字符串类(即String类)来实现的。

四、变量和数据类型
在Java中,数据的类型可以分为四种:基本数据类型、数组类型、类和接口类型。任何数据都一定是上述数据类型的一种。
其中基本数据类型可以分为四大类:布尔型、字符型、整数型和浮点型。这些类型的数据与前面介绍的常量的类型基本相同,在此不再多说。下面将整数型和浮点型变量的取值范围列出:

表一、

类型 宽度 取值范围
byte 8位 -256到256
short 16位 -32768到32767
int 32位 -2147483648到2147483647
long 64位 -9223372036854775808到9223372036854775807

表二、

进制 整数 长整数
十进制 最大正整数 2147483647(2的31次方减1) 923372036854775807L(2的63次方减1)
八进制 最大正整数 077777777777(2的31次方减1) 07777777777777777777L(2的63次方减1)
最小负整数 020000000000(-2的31次方) 04000000000000000000L(-2的63次方)
十六进制 最大正整数 0x7fffffff(2的31次方减1) 0x7fffffffffffffffL(2的63次方减1)
最小负整数 0x80000000(-2的31次方) 0x8000000000000000L(-2的63次方)

浮点数能表示的数值从小到大分别是:负无穷大、负有限值、负零、正零、正有限值及正无穷大。其中正零和负零在进行数值比较的时候是相等的,但仍有办法分辨这两个值,例如在进行1.0/0.0的时候会得到正无穷大的结果。其它非零非无穷大的有限值是以s*m*(2^e)来表示的,s和m的取值范围见下表:
表三、

类型 s m e
float +1或-1 小于2的24次方的正整数 149到104的整数
double +1或-1 小于2的53次方的正整数 1045到1000的整数

表四、float 最大值 3640282347e+38f
非零最小值 1.40239846e-45f
double 最大值 1.79769313486231570e+308
非零最小值 4.940656458412465334e-324

另外浮点数还有一些特殊值,见下表:float 最大值 Float.MAX_VALUE
最小值 Float.MIN_VALUE
正无穷大 Float.POSITIVE_INFINITY
负无穷大 Float.NEGATIVE_INFINITY
NaN Float.NaN
double 最大值 Double.MAX_VALUE
最小值 Double.MIN_VALUE
正无穷大 Double.POSITIVE_INFINITY
负无穷大 Double.NEGATIVE_INFINITY
NaN Double.NaN

与C/C++语言中不同的是,在Java语言中,所有的基本数据类型都有预设值,就是说当我们声明一个变量时,即使我们没有对它赋值,它的值也是一定的,而不像在C/C++中那样是不可预测的。具体个类型的预设值见下表:

基本数据类型 预设值
Boolean false
Char \u000
Byte (byte)0
Short (short)0
Int 0
Long 0L
Float 0.0L
Double 0.0d

五、Java与C/C++的比较
由于Java的语法直接来源于C/C++,所以Java的程序控制语句与C/C++一模一样,在此不再多说。以下重点介绍一下Java与C/C++的不同。
指针

大家在使用C语言编程的时候想必都曾经因为指针的复杂计算而烦恼,在C/C++语言编程过程中,指针可能引起许多错误,这些复杂的指针算法所产生的错误常常让人迷惑不解,导致C/C++程序员在此浪费了大量的时间。考虑到这种原因,Java中取消了指针。指针的功能由参考(reference)所取代,这使得Java中对复杂数据结构的实现更加容易,因为用对象和对象数组实现复杂的数据结构更可靠。

函数

在Java中没有C/C++中应用广泛的函数,C/C++中通过函数实现的功能在Java中都是通过类和方法来实现的。

继承

C++支持多重继承,这是一个从多个父类中派生一个类的有效办法,但这种派生很复杂,也很容易产生问题。因此,Java中没有采用多重继承,但Java的Objective C协议接口能完成C++中多重继承的所有功能。

goto语句

大家知道,在使用高级语言编程时过多的使用goto语句会使程序变得十分混乱,因此Java中也没有使用goto语句。但是不可否认,当程序比较容易控制的时候,适当使用goto语句能使程序的运行更快捷,因此Java中使用了多重break和continue语句(允许break和continue语句使用标签)实现C++种goto语句的功能。

联合和结构

在C++中有三种数据结构:联合、结构和类;Java中只有类,它可以实现上述三者的功能。

字符串

在C/C++中,字符串是通过字符数组实现的,但是由于数组的空间不是动态分配的,这容易出现越界错误,例如:常有预先设定的字符数组不能容纳后输入的字符串。在Java中,字符串是一类特定的对象,这使得字符串更具有一致性和可预见性。

Typedef、Define和预处理器

Java中不需要#define语句、预处理器或者typedef,但需要头文件。在Java中一个类的信息必须包含在一个文件中,而C/C++中有关类的信息可能分散在多个文件中。

数据类型的自动强制转换

在Java中强制一种类型的数据元素变成一种不太精确的数据类型需要编程人员采用预测方法。

阅读全文

与编译原理布尔判断必须从左往右吗相关的资料

热点内容
如何保证服务器优质 浏览:92
小微信aPP怎么一下找不到了 浏览:299
算法纂要学术价值 浏览:973
程序员你好是什么意思 浏览:799
倩女幽魂老服务器如何玩 浏览:559
电子钟单片机课程设计实验报告 浏览:997
看加密频道 浏览:379
程序员算不算流水线工人 浏览:632
三星电视我的app怎么卸载 浏览:44
简述vi编译器的基本操作 浏览:507
让程序员选小号 浏览:91
加强数字货币国际信息编译能力 浏览:584
购买的app会员怎么退安卓手机 浏览:891
程序员的种类及名称 浏览:293
美国程序员薪资 浏览:13
黑石通汇证券服务器什么时候到期 浏览:393
东方财富app里我的关注怎么看 浏览:749
bm3d单反级降噪算法 浏览:457
华为安卓机激活时间怎么查询 浏览:850
如何用优盘重装服务器系统 浏览:317