一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

當(dāng) i = i++ 后,結(jié)果究竟是什么

C語言編程基礎(chǔ) ? 來源:金吉列留學(xué)南寧 ? 作者:金吉列留學(xué)南寧 ? 2021-08-14 10:16 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言:

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

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

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

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

javap -c Test 的字節(jié)碼如下:

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的值。

關(guān)鍵是這里:

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

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

看看Test2,你就會(huì)明白正常的運(yùn)作:

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

javap -c Test2 的字節(jié)碼如下:

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.。。

現(xiàn)在明白了吧,,到底發(fā)生了什么。。

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

在gcc中,編譯一個(gè)c程序要四個(gè)階段,預(yù)處理,編譯,匯編,鏈接。我們在編譯階段后停下,這樣會(huì)得到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 和之后語句的都和輸出有關(guān)了。

我們再把初始化有關(guān)的除去,關(guān)鍵的部分是:

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

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

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

”,i);return0;}

對應(yīng)的匯編碼:

.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

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

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

”,i);return0;}

產(chǎn)生的匯編碼:

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,已經(jīng)沒問題了,但是gcc會(huì)對編譯器做一些優(yōu)化,所以保存i的值,在賦值給i,這兩條語句自然是雞肋了,就被優(yōu)化掉了。

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

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7632

    瀏覽量

    141496
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1661

    瀏覽量

    50168
  • JVM
    JVM
    +關(guān)注

    關(guān)注

    0

    文章

    160

    瀏覽量

    12610

原文標(biāo)題:C語言 & Java 解析:當(dāng) i = i++ 后,結(jié)果究竟是什么?

文章出處:【微信號:xx-cyy,微信公眾號:C語言編程基礎(chǔ)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    超聲波液位計(jì)究竟是什么?

    液位計(jì)
    jzyb
    發(fā)布于 :2025年06月03日 16:10:12

    FOC電機(jī)控制究竟該如何學(xué)?

    學(xué)習(xí)FOC電機(jī)控制究竟是學(xué)哪些內(nèi)容? 電機(jī)知識 軟件知識 純分享貼,有需要可以直接下載附件獲取完整資料! (如果內(nèi)容有幫助可以關(guān)注、點(diǎn)贊、評論支持一下哦~)
    發(fā)表于 05-09 14:09

    工程師在產(chǎn)品選型的時(shí)究竟是選CAN還是CANFD接口卡呢?

    很多工程師在產(chǎn)品選型的時(shí)候會(huì)疑惑,究竟是選CAN接口卡還是CANFD接口卡呢?兩者之間有什么區(qū)別呢?影響選擇的關(guān)鍵因素又是什么?我們今天一個(gè)一個(gè)來拆解。1.波特率傳統(tǒng)的CAN接口卡僅有一個(gè)波特率,即
    的頭像 發(fā)表于 03-21 11:37 ?359次閱讀
    工程師在產(chǎn)品選型的時(shí)<b class='flag-5'>究竟是</b>選CAN還是CANFD接口卡呢?

    三極管和MOS管的電平轉(zhuǎn)換電路為什么有毛刺?如何解決?

    ,如圖電路; 結(jié)果發(fā)現(xiàn)在3.3V這一側(cè),也就是RXD位置還是測到毛刺; 有誰知道這究竟是為什么嗎?
    發(fā)表于 03-06 06:24

    室內(nèi)導(dǎo)航究竟是如何實(shí)現(xiàn)的

    作為物聯(lián)網(wǎng)智能硬件的引領(lǐng)者,云里物里當(dāng)然不是來聊電影的,而是想借此機(jī)會(huì),和大家探討一下:室內(nèi)導(dǎo)航究竟是如何實(shí)現(xiàn)的?它背后的技術(shù)原理是什么?接下來,讓我們一起揭開室內(nèi)導(dǎo)航的神秘面紗。
    的頭像 發(fā)表于 02-12 13:50 ?498次閱讀

    ADS1298R PACE_OUT1和PACE_OUT2這兩條引腿究竟是輸入還是輸出?有什么用?怎樣使用?

    PACE_OUT1和PACE_OUT2這兩條引腿究竟是輸入還是輸出?有什么用?怎樣使用?
    發(fā)表于 02-12 07:56

    嵌入式和人工智能究竟是什么關(guān)系?

    嵌入式和人工智能究竟是什么關(guān)系? 嵌入式系統(tǒng)是一種特殊的系統(tǒng),它通常被嵌入到其他設(shè)備或機(jī)器中,以實(shí)現(xiàn)特定功能。嵌入式系統(tǒng)具有非常強(qiáng)的適應(yīng)性和靈活性,能夠根據(jù)用戶需求進(jìn)行定制化設(shè)計(jì)。它廣泛應(yīng)用于各種
    發(fā)表于 11-14 16:39

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

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

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

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

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

    電子發(fā)燒友網(wǎng)站提供《揭秘貼片功率電感發(fā)燙究竟是不是燒壞了.docx》資料免費(fèi)下載
    發(fā)表于 09-30 14:44 ?1次下載

    電感器線徑究竟是粗好還是細(xì)好

    電子發(fā)燒友網(wǎng)站提供《電感器線徑究竟是粗好還是細(xì)好.docx》資料免費(fèi)下載
    發(fā)表于 09-20 11:25 ?0次下載

    運(yùn)放輸入偏置電流的方向是流入運(yùn)放芯片還是流出運(yùn)放芯片?這個(gè)怎么確定的?

    運(yùn)放輸入偏置電流的方向究竟是流入運(yùn)放芯片還是流出運(yùn)放芯片這個(gè)怎么確定的?是不是得看運(yùn)放是三級管還是MOS管組成的,三極管還得看究竟是NPN還是PNP? 有些運(yùn)放的數(shù)據(jù)手冊上沒有給出運(yùn)放的內(nèi)部結(jié)構(gòu)
    發(fā)表于 08-23 07:29

    tas5756m使用GPIO口加內(nèi)部PLL產(chǎn)生MCLK的方法究竟是怎么樣的?

    tas5756m使用GPIO口加內(nèi)部PLL產(chǎn)生MCLK的方法究竟是怎么樣的?
    發(fā)表于 08-19 06:06

    蟬聯(lián)“第一”背后,是vivo的“快樂飛輪”正循環(huán)

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

    車載以太網(wǎng)交換機(jī)入門基本功(2)— 初識VLAN

    這么方便的VLAN,究竟是用了什么“魔法”做到的呢?
    的頭像 發(fā)表于 07-16 11:32 ?1290次閱讀
    車載以太網(wǎng)交換機(jī)入門基本功(2)— 初識VLAN