return i++ 的正确解释

yangxingmeng 2014-10-16 04:20:22
问题 :
reutrn i++; 按照正常的解释 第一步是return i; 第二部操作是 i++ 所以问题就出来了
源码
int add()
{
int i = 0;
return i++;
}
汇编后:
add:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $1, -4(%ebp)
movl -4(%ebp), %eax
addl $1, -4(%ebp)
leave
ret
.size add, .-add
问题出在 addl $1,-4(%ebp) 这个位置
即 这一句按正常理解是在 ret后面 不是在前面 如果在前面的话 在ret前面 i的值已经为 2,这个和我们见到的不一样。
...全文
772 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
li4c 2014-11-01
  • 打赏
  • 举报
回复
我也是学习了啊
bai12345633 2014-10-31
  • 打赏
  • 举报
回复
赞同版主,虽然在C语言里面我们认为是函数返回之后才++,但是在汇编中,ret之后函数栈就已经释放了,肯定不能再执行函数中的内容了,所以++肯定是在ret之前执行的,不过返回值在eax中,所以返回的值仍是++之前的值,并不矛盾。
yangxingmeng 2014-10-31
  • 打赏
  • 举报
回复
引用 8 楼 buyong 的回复:
addl $1, -4(%ebp) 这里是ebp-4, 而ebp是返回值,并没有变化
你也可以翻译下试试 我用的是centos 6.5 gcc 4.4.7
yangxingmeng 2014-10-31
  • 打赏
  • 举报
回复
引用 6 楼 mymtom 的回复:
[quote=引用 4 楼 FENGQIYUNRAN 的回复:] 全局变量: return(i++); <==> return i ; i=i+1; 局部变量: return(i++); <==> return i ; //应该没有i=i+1这个动作发生了
不管是局部变量,还是全局变量,i++一定会把i的值加一的(也许有的编译器会优化?) 楼主的汇编代码可以证明 下面程序也可以证明

#include <stdio.h>

static int *p = NULL;
static int x = 0;

int add(void)
{
    int i = 0;

    p = &i;
    return i++;
}

int
main(int argc, char *argv[])
{

    int r;

    r = add();
    x = *p;
    printf("r=%d\n", r);
    printf("x=%d\n", x);

    return 0;
}
[/quote] 十分同意你的解释 我的问题是 程序执行了一句无关的代码 并且 是做了i++ 这个动作 这个动作照我们的理解应该是在ret后 发生 但是现在 在ret前发生了 ????
fly 100% 2014-10-21
  • 打赏
  • 举报
回复
i++ 还是计算的 知识存放到其他地方了
awsqsh 2014-10-21
  • 打赏
  • 举报
回复
实际中就不应该写这样的代码。
Joseph_1118 2014-10-21
  • 打赏
  • 举报
回复
楼上正解 返回值放在eax里面的
mymtom 2014-10-17
  • 打赏
  • 举报
回复
引用 8 楼 buyong 的回复:
addl $1, -4(%ebp) 这里是ebp-4, 而ebp是返回值,并没有变化
这不科学吧?返回值是放在 %eax 中的。 楼主的汇编代码有问题,第五行是$0, 不应该是$1

add:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $16, %esp
        movl    $0, -4(%ebp)
        movl    -4(%ebp), %eax    /*  -4(%ebp) 就是 i 的地址,这里把 i 的值装入 %eax, 作为函数返回值 */
        addl    $1, -4(%ebp)         /* i 的值加 1 */
        leave
        ret
        .size   add, .-add
buyong 2014-10-17
  • 打赏
  • 举报
回复
addl $1, -4(%ebp) 这里是ebp-4, 而ebp是返回值,并没有变化
Cody2k3 2014-10-17
  • 打赏
  • 举报
回复
楼主挺能动脑筋,值得褒扬, 不过对于这个语句的解释是不正确的 return i++ 并不是理解成 return i; i++ 相反, 是 中间值 = i++; return 中间值 当return statement带有一个非空的expression的时候, expression先被evaluate, 然后convert成return所期待的type
mymtom 2014-10-17
  • 打赏
  • 举报
回复
引用 4 楼 FENGQIYUNRAN 的回复:
全局变量: return(i++); <==> return i ; i=i+1; 局部变量: return(i++); <==> return i ; //应该没有i=i+1这个动作发生了
不管是局部变量,还是全局变量,i++一定会把i的值加一的(也许有的编译器会优化?) 楼主的汇编代码可以证明 下面程序也可以证明

#include <stdio.h>

static int *p = NULL;
static int x = 0;

int add(void)
{
    int i = 0;

    p = &i;
    return i++;
}

int
main(int argc, char *argv[])
{

    int r;

    r = add();
    x = *p;
    printf("r=%d\n", r);
    printf("x=%d\n", x);

    return 0;
}
zhxianbin 2014-10-16
  • 打赏
  • 举报
回复
这种问题实际中无意义
FeelTouch Labs 2014-10-16
  • 打赏
  • 举报
回复
全局变量: return(i++); <==> return i ; i=i+1; 局部变量: return(i++); <==> return i ; //应该没有i=i+1这个动作发生了
mymtom 2014-10-16
  • 打赏
  • 举报
回复
三个字: 非常二
mymtom 2014-10-16
  • 打赏
  • 举报
回复
所以说 return i++; 的正确解释就一个字: 二 两个字: 很二
mymtom 2014-10-16
  • 打赏
  • 举报
回复
return i++; 这个根本就没有意义吧,干嘛不用 return i;
​ 博主介绍:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌项目名称基于Web的酒店客房管理系统的设计与实现系统说明3.2.1  用户模块功能分析前台模块应主要包括用户登录模块、用户注册模块、查看客房信息模块、客房预定 模块、用户留言模块、充值模块和个人信息维护模块。用户登录模块:用户通过输入注册的的账号和密码,然后进行身份验证,匹配成功 后实现登录功能。用户注册模块:用户输入合法的账号和密码可以实现注册功能。 查看客房信息模块:用户可以通过首页查看客房的价格,图片,详情等信息,从而   可以选择想要预定的房间。 客房预定模块:用户选择自己想要预定的客房后,可以通过输入相关信息进行订房操作。用户留言模块:用户可以向管理员发送留言。 充值模块:用户可以通过添加银行卡再为自己进行充值操作。 个人信息维护模块:用户可以修改自己的姓名、密码、身份证号等信息,还可以查看自己的订单。3.2.2  管理员模块功能分析对于管理员而言,一个好的管理系统总是能让酒店的管理工作事半功倍[7]。管理员 能够通过这个系统对自己的酒店情况一目了然,应该包括客户留言模块、客房管理模 块、订房信息管理模块、入住信息管理模块、统计分析模块、酒店新闻管理模块、会 员信息管理模块、员工信息管理模块、系统用户管理模块、个人信息维护模块。客户留言模块:管理员可以查看并回复用户的留言。客房管理模块:管理员可以管理客房信息,可以添加新的客房,删除已经停用的客房信息,还可以修改现有的客房信息。订房信息管理模块:管理员可以处理用户的订房请求,为用户办理入住手续。入住信息管理模块:对于没有注册的线下客户,也可以办理入住手续。统计分析模块:可以对酒店所有的入住信息进行记录和总结分析。酒店新闻管理模块:管理员可以更新网站上的新闻公告,展示图片等信息。会员信息管理模块:管理员可以查看到所有的注册会员信息,可以对会员信息进行删除,修改,添加操作。员工信息管理模块:管理员可以查看到自己公司所有的员工信息,而且还可以对员工的相关信息进行管理。系统用户管理模块:管理员可以查看到所有的系统管理员信息并对管理员信息进行管理。个人信息维护模块:管理员可以更改自己的登录密码或者是姓名、性别、手机号等 相关个人信息。​编辑 环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA;3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可4.硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS; 5.数据库:MySql 5.7版本;6.是否Maven项目:否;技术栈1. 后端:Spring+SpringMVC+Mybatis2. 前端:JSP+CSS+JavaScript+jQuery使用说明1. 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件;2. 使用IDEA/Eclipse/MyEclipse导入项目,Eclipse/MyEclipse导入时,若为maven项目请选择maven;若为maven项目,导入成功后请执行maven clean;maven install命令,然后运行;3. 将项目中springmvc-servlet.xml配置文件中的数据库配置改为自己的配置;4. 运行项目,在浏览器中输入http://localhost:8080/ 登录运行截图​编辑​编辑​编辑​编辑​编辑​编辑​编辑​编辑​编辑​编辑​编辑​编辑​编辑​编辑​编辑 用户管理控制层:package com.houserss.controller;import javax.servlet.http.HttpSession;import org.apache.commons.lang3.StringUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import com.houserss.common.Const;import com.houserss.common.Const.Role;import com.houserss.common.ServerResponse;import com.houserss.pojo.User;import com.houserss.service.IUserService;import com.houserss.service.impl.UserServiceImpl;import com.houserss.util.MD5Util;import com.houserss.util.TimeUtils;import com.houserss.vo.DeleteHouseVo;import com.houserss.vo.PageInfoVo;/** * Created by admin */@Controller@RequestMapping(/user/)public class UserController if (ip != null && ip.length() > 0) String[] ips = ip.split(,);for (int i = 0; i  

23,120

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧