while(1) 和 for(;;)有什么区别?

开发 后端
有读者问题了类似这样的问题:while(1) 和 for(;;)它们不都是无限循环吗,作用应该一样啊,它们到底有什么区别?来看一下吧。

 [[441014]]

有读者问题了类似这样的问题:while(1) 和 for(;;)它们不都是无限循环吗,作用应该一样啊,它们到底有什么区别?

要回答这个问题,其实你各自编写一段while(1) 和 for(;;)的代码,编译对比一下代码大小和汇编文件,你就大概知道了。

while(1)和for(;;)语法表达

这里先说一下while(1)和for(;;)语法表达式。

1.while语法表达 

  1. while( 表达式 )  
  2.  
  3.   语句  

其中:

  •  表达式:是循环条件
  •  语句:为循环体。

while语句的语义是:计算表达式的值,当值为真(非0)时, 执行循环体语句。其执行过程可用下图表示:

 

2.for语法表达 

  1. for(表达式1; 表达式2; 表达式3)   
  2.  
  3.   语句  

它的执行过程如下:

    1.先求解表达式1

    2.求解表达式2

    若其值为真(非0),则执行for语句中指定的内嵌语句,然后执行下面第3)步;

    若其值为假(0),则结束循环,转到第5)步。

    3.求解表达式3

    4.转回上面第2)步继续执行。

    5.循环结束,执行for语句下面的一个语句。

执行过程可用下图表示:

while(1)和for(;;)异同点

这里先说一下结论,然后再验证验证结论。

1.相同点

作用和效果都一样:都是实现无限循环的功能。

2.不同点

while(1):其中括号里面是一个条件,程序会判断真假。而括号里面的“1”永远是一个“真值”。

其中,每一次循环,编译器都要判断常量1是不是等于零。

for(;;):这两个;;空语句,编译器一般会优化掉的,直接进入死循环。

根据上面的描述,你可能会觉得:while(1) 比 for(;;) 要做更多事,汇编代码更多,代码量也更大。

但事实是这样吗?下面验证一下。

验证while(1)和for(;;)差异

我们编写分别两个文件for.c和while.c,然后分别生成汇编代码,看下情况。

1.源代码

while.c: 

  1. // filename: while.c  
  2. int main(int argc, char const *argv[])  
  3.  
  4.     while(1) 
  5.     {}  
  6.     return 0;  

for.c: 

  1. // filename: for.c  
  2. int main(int argc, char const *argv[])  
  3.  
  4.     for(;;)  
  5.     {}  
  6.     return 0;  

2.生成汇编

我们这里使用gcc编译器生成汇编,执行命令如下: 

  1. gcc -S -o while.s while.c  
  2. gcc -S -o for.s for.c 

while汇编代码: 

  1. ; filename: whiles  
  2.   .file  "while.c"  
  3.   .text  
  4.   .globl  main  
  5.   .type  main, @function  
  6. main:  
  7. .LFB0:  
  8.   .cfi_startproc  
  9.   pushq  %rbp  
  10.   .cfi_def_cfa_offset 16  
  11.   .cfi_offset 6, -16  
  12.   movq  %rsp, %rbp  
  13.   .cfi_def_cfa_register 6  
  14.   movl  %edi, -4(%rbp)  
  15.   movq  %rsi, -16(%rbp)  
  16. .L2:  
  17.   jmp  .L2  
  18.   .cfi_endproc  
  19. .LFE0:  
  20.   .size  main, .-main  
  21.   .ident  "GCC: (GNU) 9.3.0"  
  22.   .section  .note.GNU-stack,"",@progbits 

for汇编代码: 

  1. ; filename: for.s  
  2.   .file  "for.c"  
  3.   .text  
  4.   .globl  main  
  5.   .type  main, @function  
  6. main:  
  7. .LFB0:  
  8.   .cfi_startproc  
  9.   pushq  %rbp  
  10.   .cfi_def_cfa_offset 16  
  11.   .cfi_offset 6, -16  
  12.   movq  %rsp, %rbp  
  13.   .cfi_def_cfa_register 6  
  14.   movl  %edi, -4(%rbp)  
  15.   movq  %rsi, -16(%rbp)  
  16. .L2:  
  17.   jmp  .L2  
  18.   .cfi_endproc  
  19. .LFE0:  
  20.   .size  main, .-main  
  21.   .ident  "GCC: (GNU) 9.3.0"  
  22.   .section  .note.GNU-stack,"",@progbits 

你会发现,除了文件名不同,其余都相同。

当然,这里额外说一下,不同代码、不同编译器,以及不同优化等级,可能最终结果有所差异。 

 

责任编辑:庞桂玉 来源: C语言与C++编程
相关推荐

2022-09-07 18:32:57

并发编程线程

2020-03-09 20:56:19

LoRaLoRaWAN无线技术

2020-11-09 14:07:53

PyQtQt编程

2022-09-08 18:38:26

LinuxWindowsmacOS

2022-06-06 14:53:02

LoRaLoRaWAN

2022-08-02 08:23:37

SessionCookies

2024-09-09 13:10:14

2021-05-16 14:26:08

RPAIPACIO

2022-02-27 15:33:22

安全CASBSASE

2024-03-05 18:59:59

前端开发localhost

2024-05-27 00:40:00

2021-05-31 15:53:30

Cat-M1NB-IoT物联网

2022-08-22 07:06:32

MyBatisSQL占位符

2023-12-15 09:21:17

ObjectJavaString

2022-08-31 08:33:54

Bash操作系统Linux

2022-01-16 07:46:53

SpringDataASSM

2021-09-06 10:45:18

XDRMDR

2022-08-03 07:04:56

GETHTTPPOST

2020-06-28 15:11:07

LoRaWAN网络专用网络

2020-09-08 11:00:00

IaaSPaaSSaaS
点赞
收藏

51CTO技术栈公众号