bool型返回值函数,没写return语句的时候返回啥?
转载:bool型返回值函数,没写return语句的时候返回啥?
因为漏写了一个return语句,g++又没开warning,结果就悲剧了,调用的时候出现了奇怪的现象,于是就测试了一把到底没写return的时候返回什么东西。
#include <iostream>
#include <vector>
using namespace std;
bool func()
{
int i=10;
i++;
}
int main()
{
bool a = func();
bool b=true;
bool c=100;
cout<<!(a)<<endl;
cout<<!(b)<<endl;
cout<<!(c)<<endl;
cout<<(a)<<endl;
cout<<(b)<<endl;
cout<<(c)<<endl;
cout<<!10<<endl;
cout<<func()<<endl;
if(func()==true)
cout<<"true"<<endl;
if(func()==false)
cout<<"false"<<endl;
if(!func()==true)
cout<<"true"<<endl;
if(!func()==false)
cout<<"false"<<endl;
}
程序结果输出:
5
0
0
4
1
1
0
64
true
false
true
false
多次运行时上面的除0,1外的数字是随机的。
而且从if语句的判断当中我们可以看到当我们那这个没有返回语句的函数直接来判断时,他已经没有了bool变量的特性了。
再跟true,false的比较中他们都是成立的。这个时候但我们不小心使用了if else结构的时候,就永远只会执行if而不会到else的语句中了。
所以当bool返回值的函数,在没写返回语句的时候,他并不会默认地返回一个true和false,而是一个无定义的行为,会导致后面的判断出错。
那到底是怎么出现这样不合逻辑的现象的呢,让我们继续实验来一窥其中的奥秘。
要想知道其中的过程,我们首先用g++ -S来编译这份代码的汇编代码来看看。
整体汇编代码过长就不全部贴上来了,我们只来关注我们的if语句(第一个if语句和第二个)的汇编。
.L7: //第一个if语句
call _Z4funcv //首先调用func函数
xorl $1, %eax //将返回结果%eax与1作异或操作
testb %al, %al //判断al寄存器是否为0,这里的test操作就是作一次and,并设置标志位ZF;关于al 与eax的关系见下面说明。
je .L8 //根据标志位ZF作跳转。
movl $.LC0, 4(%esp)
movl $_ZSt4cout, (%esp)
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E
.L8: //第二个if语句,基本和1一样,但是由于和0作异或,因为作不作都一样,因而没有对应语句。
call _Z4funcv
testb %al, %al
je .L9
movl $.LC0, 4(%esp)
movl $_ZSt4cout, (%esp)
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
从 上面的分析中我们可以看到,但程序没有写返回语句时,我们去那返回值时,这个值就是原来返回值寄存器(eax)里面已经存在的值,这是不确定的。比如我们 这里返回了一个不为0,1的数字时,接下来我们进行bool判断时,无论与1异或,还是与0异或,都不会使改寄存器变0,因而对应的test语句也就总是 成立了。
我们使用指针去修改bool变量的值也能达到上面的同样的效果。而我们直接用数字去比较的时候却没有这个效果,是因为程序在比较之前会做一次隐性的类型转换。
附 exa, ax, ah, al 寄存器的介绍:
先请看图,图看懂了就基本解决这个了疑问了。

虽说EAX是32位的寄器,但其实只是在原有的8086CPU的寄存器AX上增加了一倍的数据位数而已。故而EAX与AX根本不可能独立,二者是整体与部分的关系。
对EAX直接赋值,若更改了低16位自然会改变了AX值,而AX又可以影响EAX整体。而AH,AL寄存器和AX之间的关系也是如此。
=========================================================================
带返回值与不带返回值函数的汇编对比:

bool型返回值函数,没写return语句的时候返回啥?的更多相关文章
- c++中带返回值函数没写return能通过编译但运行时会出现奇怪问题
c++中带返回值函数没写return能通过编译但运行时会出现奇怪问题 例如: string myFunc(){ theLogics(); } 发现调用: myFunc(); 崩溃. 但调用: cout ...
- C++中的return返回值:return0 or return -1?
C++98 中定义了如下两种 main 函数的定义方式: int main( ) int main( int argc, char *argv[] ) (参考资料:ISO/IEC 14882(19 ...
- c语言进阶4-有返回值函数
一. 从函数返回 从函数返回就是返回语句的第一个主要用途.在程序中,有两种方法可以终止函数的执行,并返回到调用函数的位置.第一种方法是在函数体中,从第一句一直执行到最后一句,当所有语句 ...
- Python函数01/函数的初识/函数的定义/函数调用/函数的返回值/函数的参数
Python函数01/函数的初识/函数的定义/函数调用/函数的返回值/函数的参数 内容大纲 1.函数的初识 2.函数的定义 3.函数的调用 4.函数的返回值 5.函数的参数 1.函数初识 # def ...
- go语言基础之有参有返回值函数的使用
1.有参有返回值函数的使用 示例1: package main //必须 import "fmt" //go官方推荐写法 func MaxAndMin(a, b int) (max ...
- 学习笔记_springmvc返回值、数据写到页面、表单提交、ajax、重定向
数据写到页面 后台往前台传数据 TestController添加 /** * 方法的返回值采用ModelAndView, new ModelAndView("index", map ...
- springmvc返回值、数据写到页面、表单提交、ajax、重定向
实验是在前一篇文章的项目上做的: 数据写到页面 后台往前台传数据 TestController添加 /** * 方法的返回值采用ModelAndView, new ModelAndView(" ...
- C++获取Lua全局变量和执行Lua多参数多返回值函数
C++代码: // LuaAndC.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #i ...
- Python 匿名函数用法和return语句
匿名函数用法1.什么是匿名函数 函数定义过程中,没有给定名称函数,python中用lambda表达式创建匿名函数 lambda只是一个表达式,函数体比def简单 lambda主题是一 ...
- C#异步执行带有返回值和参数的方法,且获取返回值
很多时候需要用到这些小知识点,做做笔记一起成长 下面是需要异步执行的方法 //获取所有的邮件 private List<EmailModel> GetEmailOnlyCount(POP3 ...
随机推荐
- Android app:回调方式实现Service向activity传递数据
一.开启服务的时候,如果我们是通过bindService来绑定服务并且要向服务传递数据,可以直接在Intent中设置bundle来达到效果,但是如果是我们需要从服务中返回一些数据到Activity中的 ...
- Bean的原始版本与最终版本不一致?记一次Spring IOC探索之旅
前言 在这个信息技术发展迅速的时代,万万没想到,Spring自2003年发展至今,仍是技术选型中的首选,某些项目甚至有Spring全家桶的情况. 在Java开发者面试当中,Spring的原理也常被面试 ...
- 最优化算法Nesterov Momentum牛顿动量法
这是对之前的Momentum的一种改进,大概思路就是,先对参数进行估计,然后使用估计后的参数来计算误差 具体实现: 需要:学习速率 ϵ, 初始参数 θ, 初始速率v, 动量衰减参数α每步迭代过程:
- WPF调用FishSpeech的Demo
写了一个FishSpeech的教程:使用FishSpeech进行语音合成推理 - 天命小猪 - 博客园 研究了一下如何调用服务器API,朗读文本. 经过调研,决定使用NAudio库播放音频.遇到了一些 ...
- SG定理
先放一个 SG 函数的定义和 SG 定理 SG 函数: \(SG(p) = \text{mex}\ {SG(t)}\) SG 定理: \(\forall n\) 个独立的子图若 \(SG(1)\ \o ...
- Hi3516EV200 编译环境配置及交叉编译软件包
基础信息 OS: Ubuntu 16.04 xenial SDK 版本: Hi3516EV200R001C01SPC012 - Hi3516EV200_SDK_V1.0.1.1 SDK 包路径:Hi3 ...
- mysql 无数据插入,有数据更新
mysql的语法与sql server有很多不同,sql server执行插入更新时可以update后使用if判断返回的@@rowcount值,然后确定是否插入,mysql在语句中无法使用类似sql ...
- MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
MongoDB 8.0这个新功能碉堡了,比商业数据库还牛 引言 MongoDB 8.0已经推出有一段时间了,相比之前的版本推出的新功能,8.0版本的新功能集中在提升性能和可维护性上面,可以说是目前性能 ...
- 华为平板+Zotero+Xodo+坚果云+Zotfile+Zotero OCR,实现论文笔记平板手写+Win自动生成,补充官方教程
需要的硬件,软件,插件和实现的最终效果,rt. 1. Win,下载Zotero,坚果云 下载网址:https://www.zotero.org/download/ 版本:Zotero 6.如果是其他版 ...
- vue 保留两位小数
前言 有时候我们需要对各种数值进行保留位数,以便于更好的展示. Html部分 template中这样使用,需要处理的字段名,再加上过滤器方法 <div class="text prim ...