色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

當 i = i++ 后,結果究竟是什么

C語言編程基礎 ? 來源:金吉列留學南寧 ? 作者:金吉列留學南寧 ? 2021-08-14 10:16 ? 次閱讀

前言:

之前有朋友跟我討論過一個問題,他問在java中,i=1;i=i++;之后的結果時什么,我一開始認為是2,但當他說答案是1的時候,我不得不想一個合理的解釋,我想,可能是因為臨時變量,當i賦值給i后,自增更改了臨時變量,所以i值并沒有改變。當我在為我的解釋表示滿意時,他們說在c語言下的答案是2,好吧,我只能說是編譯器的實現不同,當然這個答案太沒說服力了,所以尋找答案的任務就開始了。

我先在《c++ primer》上看見這樣的解釋:“++i的效率要比i++的效率高,因為i++必須要有一個臨時變量來存放i本身的值“,那么我之前只說對了臨時變量,但原因是臨時變量先用來存放i的值,然后i本身自增,之后,臨時變量賦值給左邊,這時,i的值又被 自己之前的值覆蓋了,所以又變成1,但這只是個推測,再說c語言中為什么是2?所以不得不反編譯了。。。

java的jdk自帶一個工具,javap,可以反編譯,我們用它java編譯器生成的“jvm版匯編碼”,我會寫下兩段代碼用來做對比,一種是i=i++;一種常見的j=i++;注意,我使用2作為初始值(也就是說它會被自增為3),因為1太特殊了,它在字節碼中的變量名隨處可見,而且++不是加1么,所以我用2做初值,也方便查找。

publicclassTest{publicstaticvoidmain(String[] args){inti =2; i = i++; System.out.println(i); }}

javap -c Test 的字節碼如下:

public class Test extends java.lang.Object{public Test(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object.“《init》”:()V 4: returnpublic static void main(java.lang.String[]); Code: 0: iconst_2 1: istore_1 2: iload_1 3: iinc 1, 1 6: istore_1 7: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 10: iload_1 11: invokevirtual #3; //Method java/io/PrintStream.println:(I)V 14: return}

0: iconst_2 //將int型的常量2壓棧1: istore_1 //將int型值存入變量1中

就是定義并初始化i的值。

關鍵是這里:

2: iload_1 //保存變量1的值3: iinc 1, 1 //將變量1的值自增(i現在是3了)6: istore //將之前的保存值放入變量i中(i現在又變成2了。。)

其實在2: iload_1 時,i變量的值被放在了棧中,這就是我們說的臨時存儲。。之后,又被賦了過來

看看Test2,你就會明白正常的運作:

publicclassTest2{publicstaticvoidmain(String[] args){inti =2;intj =0; j = i++; System.out.println(j); }}

javap -c Test2 的字節碼如下:

public class Test2 extends java.lang.Object{public Test2(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object.“《init》”:()V 4: returnpublic static void main(java.lang.String[]); Code: 0: iconst_2 1: istore_1 2: iconst_0 3: istore_2 4: iload_1 5: iinc 1, 1 8: istore_2 9: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 12: iload_2 13: invokevirtual #3; //Method java/io/PrintStream.println:(I)V 16: return}

4: iload_1 //變量1的值被保存(入棧)5: iinc 1,1 //i自增8 istore_2 // 彈棧,賦值給變量2.。。

現在明白了吧,,到底發生了什么。。

但是還沒完,,,,,我們還沒解釋在c語言中發生了什么。。。

在gcc中,編譯一個c程序要四個階段,預處理,編譯,匯編,鏈接。我們在編譯階段后停下,這樣會得到AT&T的匯編碼,

我們寫下兩種代碼,類似于java版

先看正常情況:

#include《stdio.h》intmain(){inti =2;intj =0; j = i++;printf(“j = %d

”,j);return0;}

編譯成匯編碼:

.file“test.c” .section .rodata.LC0:.string“j = %d

” .text.globl main.typemain, @functionmain: pushl %ebp movl %esp, %ebp andl $-16, %espsubl$32, %espmovl$2, 28(%esp)movl$0, 24(%esp) movl 28(%esp), %eax movl %eax, 24(%esp)addl$1, 28(%esp) movl $.LC0, %eax movl 24(%esp), %edx movl %edx, 4(%esp) movl %eax, (%esp)callprintfmovl$0, %eax leave ret .size main, 。-main.ident“GCC: (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3”.section.note.GNU-stack,“”,@progbits

包括 movl $.LC0, %eax 和之后語句的都和輸出有關了。

我們再把初始化有關的除去,關鍵的部分是:

movl 28(%esp), %eaxmovl %eax, 24(%esp)addl$1, 28(%esp)

保存了i的值,(放在eax中),之后又放入j中,i再自增,這就很符合大家心里的答案,那么如果是i=i++時自然就是i被賦值,再自增。。。也就是大家心中的答案了,但是真是這樣么?我們繼續看。。。。

#include《stdio.h》intmain(){inti =2;i = i++;printf(“i = %d

”,i);return0;}

對應的匯編碼:

.file“test2.c” .section .rodata.LC0:.string“i = %d

” .text.globl main.typemain, @functionmain: pushl %ebp movl %esp, %ebp andl $-16, %espsubl$32, %espmovl$2, 28(%esp)addl$1, 28(%esp) movl $.LC0, %eax movl 28(%esp), %edx movl %edx, 4(%esp) movl %eax, (%esp)callprintfmovl$0, %eax leave ret .size main, 。-main.ident“GCC: (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3”.section.note.GNU-stack,“”,@progbits

關鍵部分就省一句了 addl $1, 28(%esp)這簡直就是。。。。看我的test3.c吧。。。

#include《stdio.h》intmain(){inti =2;i++;printf(“i = %d

”,i);return0;}

產生的匯編碼:

aiqier@aiqier-laptop:~/c/test3$ cat test3.s

.file“test3.c” .section .rodata.LC0:.string“i = %d

” .text.globl main.typemain, @functionmain: pushl %ebp movl %esp, %ebp andl $-16, %espsubl$32, %espmovl$2, 28(%esp)addl$1, 28(%esp) movl $.LC0, %eax movl 28(%esp), %edx movl %edx, 4(%esp) movl %eax, (%esp)callprintfmovl$0, %eax leave ret .size main, 。-main.ident“GCC: (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3”.section.note.GNU-stack,“”,@progbits

恩,在c語言中i=i++;居然跟i++;的匯編代碼一樣,按正常的邏輯(我們之前的分析),i=2;i=i++;i的值是3,已經沒問題了,但是gcc會對編譯器做一些優化,所以保存i的值,在賦值給i,這兩條語句自然是雞肋了,就被優化掉了。

總結,我們發現對于i++保存的臨時值,java中是自增在返回臨時值,而c語言中是返回臨時值后,在自增,所以這就是為什么i=i++在這兩種語言中不同的結果了,c#我就不知道了,有興趣的同學可以試試,python么,沒有++啦,呵呵,如果我的分析有什么不對之初,希望能與你一起探討。

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C語言
    +關注

    關注

    180

    文章

    7605

    瀏覽量

    136903
  • 編譯器
    +關注

    關注

    1

    文章

    1634

    瀏覽量

    49139
  • JVM
    JVM
    +關注

    關注

    0

    文章

    158

    瀏覽量

    12234

原文標題:C語言 & Java 解析:當 i = i++ 后,結果究竟是什么?

文章出處:【微信號:xx-cyy,微信公眾號:C語言編程基礎】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    嵌入式和人工智能究竟是什么關系?

    嵌入式和人工智能究竟是什么關系? 嵌入式系統是一種特殊的系統,它通常被嵌入到其他設備或機器中,以實現特定功能。嵌入式系統具有非常強的適應性和靈活性,能夠根據用戶需求進行定制化設計。它廣泛應用于各種
    發表于 11-14 16:39

    PCM1861 INT腳究竟是輸出還是輸入?

    這個芯片activce或是idle. 是否有人解釋下,INT腳究竟是輸出還是輸入。我希望是輸出,我需要讀取到是否有analog audio輸入的信息。 或者,輸入輸出與否還要靠其他什么地方設置? 盼望有人回復解答,不勝感激!
    發表于 10-29 07:29

    超高頻讀寫器究竟是什么,能做什么?一文讀懂!

    在物聯網技術日新月異的今天,超高頻讀寫器作為射頻識別(RFID)技術的重要組成部分,正逐漸滲透到我們生活的各個領域。那么,超高頻讀寫器究竟是什么?它又能做些什么呢?本文將帶您一探究竟。一、超高頻
    的頭像 發表于 10-23 14:41 ?222次閱讀
    超高頻讀寫器<b class='flag-5'>究竟是</b>什么,能做什么?一文讀懂!

    揭秘貼片功率電感發燙究竟是不是燒壞了

    電子發燒友網站提供《揭秘貼片功率電感發燙究竟是不是燒壞了.docx》資料免費下載
    發表于 09-30 14:44 ?0次下載

    電感器線徑究竟是粗好還是細好

    電子發燒友網站提供《電感器線徑究竟是粗好還是細好.docx》資料免費下載
    發表于 09-20 11:25 ?0次下載

    tas5756m使用GPIO口加內部PLL產生MCLK的方法究竟是怎么樣的?

    tas5756m使用GPIO口加內部PLL產生MCLK的方法究竟是怎么樣的?
    發表于 08-19 06:06

    蟬聯“第一”背后,是vivo的“快樂飛輪”正循環

    “快樂公司”究竟是如何脫離紅海競爭?
    的頭像 發表于 07-30 08:24 ?2925次閱讀
    蟬聯“第一”背后,是vivo的“快樂飛輪”正循環

    請問cH340G的TX引腳電平究竟是3v還是5v?

    用CD34G來實現usb轉串口的時候,直接用usb口的5v作為電源電壓,它的tx引腳輸出的高電平究竟是5v還是3v,我實測是3v,但網上有的人是5v,想進一步得到大家的確認。
    發表于 05-14 08:15

    MPLS究竟是什么?

    由于運行 MPLS 的服務提供商只查看數據包上的標簽,而不是 IP 本身,這使得服務提供商能夠使用 MPLS 為此類客戶提供 VPN 服務。
    發表于 04-26 16:09 ?389次閱讀
    MPLS<b class='flag-5'>究竟是</b>什么?

    工業物聯網究竟是什么呢?它又有哪些作用呢?

    隨著科技的快速發展,物聯網技術已經逐漸滲透到我們生活的各個角落,而 工業物聯網(IIoT) 更是引領著工業領域的數字化轉型。那么,工業物聯網究竟是什么呢?它又有哪些作用呢?本文將對此進行深度解析
    的頭像 發表于 04-22 15:26 ?399次閱讀

    STM32擦除數據究竟是0x00還是0xff ?

    STM32擦除數據究竟是0x00還是0xff ,百度查了許多發現大多數都是0xff的多,都說SD卡(TF)儲存介質是Flash 所以擦除后為0xff,但是我遇到了讀出來的數據是0x00的情況,為什么呢
    發表于 04-18 07:59

    MOSFET的柵源振蕩究竟是怎么來的?柵源振蕩的危害什么?如何抑制

    MOSFET的柵源振蕩究竟是怎么來的呢?柵源振蕩的危害什么?如何抑制或緩解柵源振蕩的現象呢? MOSFET(金屬-氧化物-半導體場效應晶體管)的柵源振蕩是指在工作過程中,出現的柵極與源極之間產生
    的頭像 發表于 03-27 15:33 ?1719次閱讀

    吸塵器究竟是如何替你“吃灰”的【其利天下技術】

    如今,吸塵器已成為大多數人居家必備的小家電產品,那么說起吸塵器,你對吸塵器有了解多少呢?不知道大家知不知道它的原理是什么?今天我們就來說一說吸塵器究竟是如何替你“吃灰”的。
    的頭像 發表于 03-07 21:17 ?881次閱讀
    吸塵器<b class='flag-5'>究竟是</b>如何替你“吃灰”的【其利天下技術】

    “其貌不揚”的共模電感究竟是如何做到抗干擾的呢?

    “其貌不揚”的共模電感究竟是如何做到抗干擾的呢? 共模電感是一種用于濾除電子設備中的共模噪聲的重要元件,其主要作用是提供阻抗來濾除共模干擾信號。盡管外觀看起來“其貌不揚”,但共模電感通過其特殊
    的頭像 發表于 01-11 16:27 ?783次閱讀

    RL究竟是如何與LLM做結合的?

    強化學習(Reinforcement Learning, RL)的核心概念可簡單概括為:一個機器人(Agent)在看到了一些信息(Observation),自己做出一個決策(Action),隨即根據采取決策得到的反饋(Reward)來進行自我學習(Learning)的
    的頭像 發表于 01-03 16:34 ?1148次閱讀
    RL<b class='flag-5'>究竟是</b>如何與LLM做結合的?
    主站蜘蛛池模板: 亚洲国产精品无码2019| 欧美人与禽ZOZO性伦交视频 | 男女生爽爽爽视频免费观看| 亚洲、国产综合视频| 东热rq大乱交| 色悠久久久久综合欧美99| caoporn 超碰在线视频| 久久伊人中文字幕有码| 亚洲熟伦熟女专区| 精品无码三级在线观看视频| 亚洲国产精品免费观看| 国产在线公开视频| 亚洲va精品中文字幕| 国内精品七七久久影院| 亚洲AV蜜桃永久无码精品无码网 | 国产午夜精品理论片在线| 文中字幕一区二区三区视频播放 | 成年人免费观看视频网站| 暖暖视频 免费 高清 日本8| 99久久99| 琪琪see色原网色原网站| xxxx俄罗斯1819| 日韩一区二区天海翼| 国产国拍精品AV在线观看| 乡村教师电影版| 好紧的小嫩嫩17p| 在线观看永久免费网站| 母狗黄淑珍| 成人久久欧美日韩一区二区三区| 日日夜夜撸 在线影院| 国产露脸无码A区久久蘑菇| 亚洲欧美日韩精品自拍| 久久热在线视频精品店| beeg日本老妇人| 深爱激情站| 精品蜜臀AV在线天堂| 69国产精品人妻无码免费| 秋霞电影院午夜伦高清| 国产午夜精AV在线麻豆| 《乳色吐息》无删减版在线观看 | 9位美女厕所撒尿11分|