转载: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语句的时候返回啥?的更多相关文章

  1. c++中带返回值函数没写return能通过编译但运行时会出现奇怪问题

    c++中带返回值函数没写return能通过编译但运行时会出现奇怪问题 例如: string myFunc(){ theLogics(); } 发现调用: myFunc(); 崩溃. 但调用: cout ...

  2. C++中的return返回值:return0 or return -1?

    C++98 中定义了如下两种 main 函数的定义方式: int main( ) int main( int argc, char *argv[] )   (参考资料:ISO/IEC 14882(19 ...

  3. c语言进阶4-有返回值函数

    一.         从函数返回 从函数返回就是返回语句的第一个主要用途.在程序中,有两种方法可以终止函数的执行,并返回到调用函数的位置.第一种方法是在函数体中,从第一句一直执行到最后一句,当所有语句 ...

  4. Python函数01/函数的初识/函数的定义/函数调用/函数的返回值/函数的参数

    Python函数01/函数的初识/函数的定义/函数调用/函数的返回值/函数的参数 内容大纲 1.函数的初识 2.函数的定义 3.函数的调用 4.函数的返回值 5.函数的参数 1.函数初识 # def ...

  5. go语言基础之有参有返回值函数的使用

    1.有参有返回值函数的使用 示例1: package main //必须 import "fmt" //go官方推荐写法 func MaxAndMin(a, b int) (max ...

  6. 学习笔记_springmvc返回值、数据写到页面、表单提交、ajax、重定向

    数据写到页面 后台往前台传数据 TestController添加 /** * 方法的返回值采用ModelAndView, new ModelAndView("index", map ...

  7. springmvc返回值、数据写到页面、表单提交、ajax、重定向

    实验是在前一篇文章的项目上做的: 数据写到页面 后台往前台传数据 TestController添加 /** * 方法的返回值采用ModelAndView, new ModelAndView(" ...

  8. C++获取Lua全局变量和执行Lua多参数多返回值函数

    C++代码: // LuaAndC.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #i ...

  9. Python 匿名函数用法和return语句

    匿名函数用法1.什么是匿名函数    函数定义过程中,没有给定名称函数,python中用lambda表达式创建匿名函数    lambda只是一个表达式,函数体比def简单    lambda主题是一 ...

  10. C#异步执行带有返回值和参数的方法,且获取返回值

    很多时候需要用到这些小知识点,做做笔记一起成长 下面是需要异步执行的方法 //获取所有的邮件 private List<EmailModel> GetEmailOnlyCount(POP3 ...

随机推荐

  1. 开启 Typecho 的 gzip 压缩

    简介 GZip压缩,是一种网站速度优化技术,也是一把SEO优化利器,许多网站都采用了这种技术,以达到提升网页打开速度.缩短网页打开时间的目的. 网站采用Gzip压缩,还有一个好处,就是让你少了一份流量 ...

  2. 通过fetch_mcp,让Cline能够获取网页内容。

    fetch_mcp介绍 GitHub地址:https://github.com/zcaceres/fetch-mcp 此MCP服务器提供了以多种格式(包括HTML.JSON.纯文本和Markdown) ...

  3. 面试题32 - I. 从上到下打印二叉树

    地址:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/ <?php /** 从上到下打印出二 ...

  4. 使用QT开发远程linux服务器过程

    1.添加设备为通用linux 2.设置ip用户名 3.创建私钥文件,原来有的qtc那俩个文件删掉. 4.部署公钥,前提是测试链接要出现成功 5.在kits里添加编译环境设置编译器为32位或者64 6. ...

  5. ohpm : 无法将“ohpm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。

    ohpm : 无法将"ohpm"项识别为 cmdlet.函数.脚本文件或可运行程序的名称. 造成该问题有两个: 没有配置好 ohpm 的环境变量. 没有配置好 PowerShell ...

  6. UNIX 系统

    UNIX 系统的历史,UNIX 是操作系统的开山鼻祖,是操作系统的发源地,后来的 Windows 和 Linux 都参考了 UNIX. 有人说,这个世界上只有两种操作系统: UNIX 和类 UNIX ...

  7. Linux® 容器

    是与系统其他部分隔离开的一系列进程.运行这些进程所需的所有文件都由另一个镜像提供,这意味着从开发到测试再到生产的整个过程中,Linux 容器都具有可移植性和一致性.因而,相对于依赖重复传统测试环境的开 ...

  8. 探秘Transformer系列之(18)--- FlashAttention

    探秘Transformer系列之(18)--- FlashAttention 目录 0x00 概述 0.1 问题 0.2 其它解决方案 0.3 Flash Attention 0x01 背景知识 1. ...

  9. 【Spring】JdbcTemplate的使用方法

    概念和准备 什么是 JdbcTemplate Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作 准备工作 引入相关 jar 包 在 spring 配置文件 ...

  10. Git Bash 无法输入中文

    场景重现 有个小伙伴的电脑上 Git Bash 里死活无法输入中文, 导致 git 提交信息没法用中文写... git commit -m "无法输入中文" 解决办法 在 Git ...