Linux gcc for 循环中 i=i++ 会造成死循环问题及 ++i / i++ 汇编分析

在把 Windows 程序移植到 Linux 时遇到了死循环,最后定位到了类似这种的语句 for (i = 0; i < 1; i = i++),

别问我是谁写的,为什么这么写(泪目)。

根据C语言的常识, i = i++ 应该等价于 i++, Windows 上确实是这样,但 Linux 不是,这应该是编译器差异造成的。

--------------------------------------- 可 i 的分割线 No.0 -----------------------------------------------------------------------------------------------

那么问题来了,为什么会这样呢?

arm-linux-gcc  -S  i.c 汇编一下,编译结果和源码如下(gcc 汇编的代码不太好看,所以用了 arm 版的):

首先介绍一下出现的汇编指令:

mov r3, #0       (把常数值赋值给 r3,相当于 r3=0)

str r3, [fp, #-8] (把 r3 的值存储到内存地址 [fp, #-8])

ldr r3, [fp, #-8] (把内存地址 [fp, #-8] 的值载入到 r3,和 str 相反)

add r2, r3, #1    (r2 = r3 + 1)

okey, 其实是先把 i 的原始值缓存到 r3,然后加1的值赋给 r2,r2会更新 i 值(因为 i++), 最后 r3 也会更新 i 值(因为 i=),

至于为何是这个顺序,请呼叫大神吧。所以,i 的值会一直为0,导致文章开头的 for 循环就死了。

--------------------------------------- 可 i 的分割线 No.1 -----------------------------------------------------------------------------------------------

为了好理解,我还汇编出了 j=i++,如下:

j = i++ : 还是先缓存 i 的原始值,然后把加1的 i 值赋给 i,最后在把缓存的 i 的原始值赋给 j(和 i = i++ 的顺序一样)。

j = ++i : 先更把加1的 i 值赋给 i,然后再取出 i 值赋给 j 。

--------------------------------------- 可 i 的分割线 No.2 -----------------------------------------------------------------------------------------------

此外,一直想看看i++++i 的汇编有什么不同,结果如下:

因为一直都听过这个说法,for 循环中 ++i 的效率比 i++ 高,但从上图中可以看成,在单独的语句中,

++i 和 i++ 是一样的(gcc 系列编译器),不过还是推荐用 ++i,为了移植性,不能相信编译器。

时间: 2024-10-12 14:20:10

Linux gcc for 循环中 i=i++ 会造成死循环问题及 ++i / i++ 汇编分析的相关文章

Linux中处理循环中scanf引起的缓冲区清除问题

fflush(stdin)在gcc里不能够清空缓冲区,为了解决这个问题可以用getchar()处理这个问题,如下面代码所示: #include <stdio.h> #define N 10 struct student { long num; char name[20], sex; int age, score; }; void main() { int s,t=-1; long xuehao; struct student stu[N]; printf("Please input

嵌入式Linux GCC常用命令

本文和大家分享的主要是嵌入式Linux GCC常用命令相关内容,一起来看看吧,希望对大家学习嵌入式Linux有所帮助. 1.简介 GCC 的意思也只是 GNU C Compiler 而已.经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言:它现在还支持 Ada 语言.C++ 语言.Java 语言.Objective C 语言.Pascal 语言.COBOL语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等.而 GCC 也不再单只是 GNU C 语言编译器的意思了,而是变成了 

Linux GCC

转载自 http://www.cnblogs.com/ggjucheng/archive/2011/12/14/2287738.html 1简介 GCC 的意思也只是 GNU C Compiler 而已.经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言:它现在还支持 Ada 语言.C++ 语言.Java 语言.Objective C 语言.Pascal 语言.COBOL语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等.而 GCC 也不再单只是 GNU C 语言编译器的意思

for 循环中 i++和 ++i

在标准C语言中, i++和 ++i的区别显而易见. 但是,当在for循环中使用 i++和 ++i的时候,会发现.只要这两种语句不用来赋值操作(作为右值,赋值给左值),那么这两种写法其实是一样的. for中其实不管是i++或++i都是在for循环体全部执行完毕后才执行, 如: for(int i = 0;i < 10; i++){System.out.println(i);}等同于for(int i = 0;i < 10; ){System.out.println(i);            

Linux gcc getcwd()的实现 zhuan

通过getcwd()可以获取当前工作目录. 1 #include <unistd.h> 2 3 char *getcwd(char *cwdbuf, size_t size); Linux gcc getcwd()的实现 zhuan

循环中的let和const声明

一.循环中的let声明 每次循环的时候let声明都会创建一个新变量i,并将其初始化为i的当前值,所以循环内部创建的每个函数都能得到属于他们的i的副本. 最初的: for (var i = 0 ; i < 10 ; i++) { array.push(function(){    console.log(i) })  };    array.forEach(function(func){         func()    }) 优化后: var array=[];   for (var i =

for循环中i--的妙用 及 两变量互换数值的问题

int[] array = new int[4]; for(int i = 0; i < array.length; i++){ array[i] = (int)(Math.random() * 10); for(int j = 0; j < i; j++){ if(array[i] == array[j]){ //相同就重取随机数 i--; break; } } } 以上是一段取四个不相等随机数的代码,这里的 i-- 是这段代码的核心. 在内层for循环中,一旦 array[i] == ar

【转】Linux GCC常用命令

转自:http://www.cnblogs.com/ggjucheng/archive/2011/12/14/2287738.html 1简介 2简单编译 2.1预处理 2.2编译为汇编代码(Compilation) 2.3汇编(Assembly) 2.4连接(Linking) 3多个程序文件的编译 4检错 5库文件连接 5.1编译成可执行文件 5.2链接 5.3强制链接时使用静态链接库 1简介 GCC 的意思也只是 GNU C Compiler 而已.经过了这么多年的发展,GCC 已经不仅仅能

linux gcc attribute

_attribute__((error("message"))) Declare that calling the marked function is an error. __attribute__((warning("message"))) Declare that calling the marked function is suspect and should emit a warning. __attribute__((deprecated)) Decla