CONDITIONS and BRANCHES in C++(if statements)

CONDITIONS and BRANCHES in C++(if statements)

C++ 条件和分支


if 语句

条件语句,if语句或者分支结构到底意味着什么?当代码需要去评估某个值来决定我们下一步执行的操作。当我们写if语句的时候,实际上有两件事发生,当我们运行代码时,就会有对实际条件情况的比较。该代码有实际条件的评估,然后又依赖于该评估的分支,所以换句话说,如果我们的条件评估为真,我们需要跳转到源代码的某个部分,如果评估为假,我们需要跳转到源代码的另一部分。当然我说的是源代码,但在一个正在运行的程序中,它实际上意味着机器指令,所以换句话说,我们跳转到我们机器代码或者CPU指令的分支中,或者跳转到我们的另一部分CPU指令中。

现在当我们启动一个引用程序时,整个应用程序及其模块都被加载到内存,所以基本上构成我们程序的指令都是存储在内存中。当我们遇到分支的条件时,我们告诉计算机跳转到这部分内存然后开始执行我们的指令,由于所有在内存和分支中跳跃,这实际上比我所说的要复杂一些,这里有很多值得探索的东西。我们比较条件,然后跳转到内存中的其他部分,然后执行指令。实际上意味着if语句和分支确实会带来一些开销。如果你尝试编写非常快的代码,你可能会决定不使用if语句。

实际上代码优化代码避免分支,避免比较,因为这样会让程序变慢。这个系列的最后我们会开一些将分支结构去除的优化教程。无论如何不要让这太复杂,记住一个条件在我们的if语句的条件下,如果为真,那么我们想要跳转或执行一组代码,这就是基础的全部内容。

Equality Operator

int x = 5;
bool comparisonResult = x == 5;

==被称为相等运算符,它基本上是检查x是否等于5,等于为true,不等于为false。这个运算符是这个含义的原因是它在C的标准库中已经被加重载过了。某人写了一个函数,可以接纳两个整数,然后从内存中调出整数,进行比较确保是否相等。

实际上在大多数原始数据结构中,当你检查两个整数是否相等时,其实时把他们的四个字节给抓取出来,然后逐字节逐位地进行比较,在内存中对应位的二进制数都得相同,才能使这个整数相等

if(comparisonResult)
{
	//主体语句
	Log("Hello World!");
}

运行代码,控制台输出Hello World!

如果我们想输入了解背后的运行原理,我们可以查看汇编代码。

Disassembly View

调试代码的时候右击查看反汇编
在这里插入图片描述

int main()
{
00007FF7A5A165A0  push        rbp  
00007FF7A5A165A2  push        rdi  
00007FF7A5A165A3  sub         rsp,128h  
00007FF7A5A165AA  lea         rbp,[rsp+20h]  
00007FF7A5A165AF  lea         rcx,[__08FD88C6_main@cpp (07FF7A5A230E6h)]  
00007FF7A5A165B6  call        __CheckForDebuggerJustMyCode (07FF7A5A113F2h)  
	int x = 6;
00007FF7A5A165BB  mov         dword ptr [x],6  //将6加载到寄存器中

	bool comparisonResult = x == 5;
00007FF7A5A165C2  cmp         dword ptr [x],5  //将5加载到同一个寄存器中
00007FF7A5A165C6  jne         main+34h (07FF7A5A165D4h)  //jne(jump not equal) 
														//不等于会跳转 07FF7A5A165D4h 这个内存(实际在下面能看到这个内存)
00007FF7A5A165C8  mov         dword ptr [rbp+0F4h],1   //这行代表真。
00007FF7A5A165D2  jmp         main+3Eh (07FF7A5A165DEh)  
00007FF7A5A165D4  mov         dword ptr [rbp+0F4h],0   //跳转到这一行
													   //将值0移动到这个寄存器中(事实这个结果就是false,0代表false)
00007FF7A5A165DE  movzx       eax,byte ptr [rbp+0F4h]  
00007FF7A5A165E5  mov         byte ptr [comparisonResult],al  
	if (comparisonResult)
00007FF7A5A165E8  movzx       eax,byte ptr [comparisonResult]  //把变量加载到寄存器中
00007FF7A5A165EC  test        eax,eax    //查看我们的eax寄存器是否为真
00007FF7A5A165EE  je          main+5Ch (07FF7A5A165FCh)   //跳转到相等的地方
	{
		Log("Hello World!");
00007FF7A5A165F0  lea         rcx,[string "Hello World!" (07FF7A5A1AC18h)]  
00007FF7A5A165F7  call        Log (07FF7A5A11352h)  
	}

	std::cin.get();
00007FF7A5A165FC  mov         rcx,qword ptr [__imp_std::cin (07FF7A5A21190h)]  
00007FF7A5A16603  call        qword ptr [__imp_std::basic_istream<char,std::char_traits<char> >::get (07FF7A5A21150h)]  
}

下面的汇编代码对应上面的语句。对照汇编代码,我可以实际上发生了什么。

if 语句

如果我们创建一个布尔值实际上会占用一个字节的内存,我们没有必要确保那位设置为1,所以就像真的一样,如果有任何东西,不是0,那么就为真。如果我们只处理一位,他们它可能会是真的,当然我们只有两个可能的值0和1。如果它是0,那它会是假的。

上述是Debug模式下,编译器没有优化,x=6和5不一定要到运行的时候再比较,我们可以在编译的时候就可以进行比较。这种称为常数折叠的技术,所以它把这些转到一个常变量中,因为这些常量都会在编译时被知晓。如果比较结果,它实际上和这个if语句全部放在一起。既然if语句里面不会执行,那么就不需要编译了。当然这些都是在优化模式下进行,如果你想知道原理还是要在debug模式下。

布尔值实际上只是一个整数它时0表示false而不是其他任何东西,例如1表示true,所以if语句实际上在做什么是检查这个数字是不是0,如果是0那么它就不会执行那个if语句,但如果它是0以外的任何东西,比如1它会跳到if语句里面。

if(x==5)
	Log("Hello World!");

也可以直接把x=5直接写到f语句里面 。还可以将if语句的大括号取消,这样写。如果将Log函数和if语句写在一行,那么调试的时候会有影响。

if(x)
	Log("Hello World!");

我们也可以这样写if(x),if仅仅判断值是不是0。

const char* ptr="Hello";
if(ptr)
	Log("Hello World");

这样对检查指针也很常见,如果我们想检查指针是否为null,null当然是0。我们基本上可以像这样将指针放到if语句条件中,看看它是否是null。if判断的是ptr是否是有效值。这样只能在C++中,但是不能再java或者C#中

else if 语句

const char* ptr = nullptr;
if(ptr)
	Log("Hello World!");
else if (ptr == "Hello")
	Log("ptr is Hello")

其实是

if(ptr)
	Log("Hello World!");
else 
{
	if(ptr == "Hello")
		Log("ptr is Hello")
}

上面的语句可以拆分成下面的形式,else if 并不是什么关键字组合,它其实就是else{ if() }的简写形式。C++中没有else if这样的关键字,就仅仅是else 和if的组合

编程有两个真实的部分,一种是数学编程,一种是逻辑编程,只是我喜欢将编程分为这两个部分。当然也有些编程你只要进行数学运算即可。大多数快速代码实际上是通过像数学运算一样编写的,前面提到的逻辑编程就比较少,他们完全是和逻辑相关的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值