惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

W
WeLiveSecurity
T
The Exploit Database - CXSecurity.com
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Security @ Cisco Blogs
T
Threat Research - Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
腾讯CDC
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Blog of Author Tim Ferriss
Microsoft Azure Blog
Microsoft Azure Blog
罗磊的独立博客
F
Full Disclosure
博客园 - 【当耐特】
C
CERT Recently Published Vulnerability Notes
Engineering at Meta
Engineering at Meta
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Threatpost
I
Intezer
V2EX - 技术
V2EX - 技术
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The Hacker News
The Hacker News
小众软件
小众软件
Google DeepMind News
Google DeepMind News
T
Tailwind CSS Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
B
Blog RSS Feed
Microsoft Security Blog
Microsoft Security Blog
N
News | PayPal Newsroom
MyScale Blog
MyScale Blog
AI
AI
Vercel News
Vercel News
Spread Privacy
Spread Privacy
美团技术团队
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The GitHub Blog
The GitHub Blog
V
Vulnerabilities – Threatpost
Schneier on Security
Schneier on Security
Cyberwarzone
Cyberwarzone
G
GRAHAM CLULEY
Help Net Security
Help Net Security
Hacker News: Ask HN
Hacker News: Ask HN
Google DeepMind News
Google DeepMind News
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
U
Unit 42
L
LangChain Blog
Recent Announcements
Recent Announcements

博客园 - wiseman

universal image loader在listview/gridview中滚动时重复加载图片的问题及解决方法 升级framework4.0后form认证票据失效的问题 vs2010下连接sql2000的一些问题 IIS ftp的一个问题:home directory inaccessible MS SQLServer2000 的孤立用户问题及解决. 服务器部署.NET 3.5的问题 愚蠢的错误 - wiseman - 博客园 VS2005项目迁移至VS2008初体验. Linux学习笔记:REHL AS4的上网配置,Http服务安装及配置,ftp服务的安装及配置 Linux学习笔记:需求和安装 通过了解MySpace的六次重构经历,来认识分布式系统到底该如何创建. WebService problem:The remote name could not be resolved 烦人的CommunityServer 简单的WEB程序压力测试. MS ASP.NET AJAX 1.0 Released! 用C#编写flash Application! Atlas提交中文时乱码的完整解决方案. 困扰了两天的问题... .NET2.0中Form验证的问题.
一句C#代码的分析.
wiseman · 2006-09-12 · via 博客园 - wiseman

题记:本文纯粹是出于研究的目的,实际上下面的那种写法是根本不被提倡,也不会有人使用的.代码的优劣在于保证性能和程序扩展性的情况下,本身表述清晰与否,一味的追求简化是没有任何好处的,除了让你自己觉得很cool.当然,读你代码的人绝对不会那么认为.

昨天在CSDN首页看到一个帖子,问,i=0;i=i++;最后得出的i等于多少?
答案很容易得出,Console.WriteLine(i)可以看到是0.

答案当然不是我们所关注的,为什么会是0呢?如果是i=0;j=i++;那任何人都能得出j=0这个结果,但是这里是给i自己赋值,但是i++这个自增操作又确实执行了,那最后为什么会是i=0呢?隐约觉得应该是出栈顺序造成的结果,猜测是没有意义的,就让我们看看IL代码到底是怎么回事.

这是一段简单的C#代码:

 static void Main(string[] args)
        
{
            
int i = 0;
            i 
= i++;
            Console.WriteLine(i);
        }


对应的IL代码如下:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  
// Code size       17 (0x11)
  .maxstack  
3
  .locals init (
[0] int32 i)
  IL_0000:  nop             
  IL_0001:  ldc.i4.
0   
  IL_0002:  stloc.
0    
  IL_0003:  ldloc.
0   
  IL_0004:  dup       
  IL_0005:  ldc.i4.
1  
  IL_0006:  
add          
  IL_0007:  stloc.
0   
  IL_0008:  stloc.
0   
  IL_0009:  ldloc.
0 
  IL_000a:  call       void 
[mscorlib]System.Console::WriteLine(int32)
  IL_000f:  nop
  IL_0010:  ret
// end of method Program::Main

下面让我们分析一下这段IL代码.
到IL_003为止,这里实现了一次数据的入栈操作,即把变量v0的值push到了ES寄存器里.对应的C#代码是int i = 0;
此时的栈情况如下:
[0] //此时v0=0

然后执行了dup操作,复制栈顶元素,这里对应的操作我们可以理解为是i = i++;中的右边i的出现.
此时的栈的情况如下:
[0,0] //v0=0

接下来是在ES中再申请4byte的空间,值为1.注意,这里并未把值赋给变量,因为这正是常量的申明.
栈情况如下:
[v0,0,1] //v0=0
这里的1的申明实际上是i++操作引起的.单独的i++等价i+=1;如果我们查看IL的话,也会发现两者是一模一样的

随后就进入了关键的部分:操作和出栈.
add执行的加操作,需要两个参数,因为结果依然是在ES中存储中,因此操作完后,栈的情况如下:
[0,0+1]
到现在,已经很清楚了,接下来的两次出栈做的是同一件事,弹出栈顶元素,赋给v0.如下:
[0,0+1]-->pop 1 to v0,v0 = 1;
[0]-->pop 0 to v0,v0 = 0;
v0正是最终i的值,为0.

疑点:
为何最后会有两次出栈操作?
答案是,在i = i++;中实际上有两部操作,i = 右边(未知数);i = i + 1;因此,必然存在两次出栈.

最后,实际上在C/C++中i=i++后,得出的结果为1,至于为什么,即使我们不反汇编也应该明白,肯定是出栈或入栈的顺序导致的,有兴趣的朋友不妨去试着分析一下:)