普通for循环和增强for循环的使用小结

本文探讨了for循环与增强for循环(foreach)的区别及适用场景。通过具体代码实例展示了不同循环方式在ArrayList与LinkedList上的性能表现,并指出增强for循环在多线程环境下可能存在的问题。
for循环分为两种:
第一种为普通的for循环
这种for循环通常需要三个步骤即 for(初始表达式;条件表达式;递增表达式)有时候递增表达式也可以省去,一般是在使用Iterator迭代时(Iterator的hasNext方法判断时,可以省去递增表达式)。这种for循环很常用。
第二种为增强的for循环(也就是foreach循环)
这种for循环的内部是调用了Iterator实现的(实现了Iterator接口),和Iterator遍历效果是一样(你可以断点调试跟踪代码看看内部原理),主要用于遍历数组、集合的每一个元素。优点是写法简便,无需获得数组、集合长度,也无需根据索引来访问元素。缺点是不能在循环里动态的删除元素和获取元素下标,还有一点,在多线程下使用增强for来改变元素会出错误,因为通过迭代器实现的增强for对该数组或集合会现有一个拷贝,改变元素是会导致不能正常遍历数组和集合。所以说多线程下增强for是不安全不推荐用。

拿数组ArrayList和链表LinkedList来区分记忆:
1.ArrayList由于使用数组实现,因此下标明确,最好使用普通for循环。
2.而对于 LinkedList 由于获取一个元素,要从头开始向后找,因此建议使用增强for循环,也就是iterator。
看代码吧,让这个问题更明朗些。


import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ForTest {
 public static void main(String[] args) {
   //List<Integer> list = new ArrayList<Integer>();
  List<Integer> list = new LinkedList<Integer>();
  for (int i = 0; i < 60000; i++) {
   list.add(5);
  }
  int resutl = 0;
  long start = System.currentTimeMillis();
  //使用普通for循环
  for (int i = 0; i < list.size(); i++) {
   resutl = list.get(i);
  }
  System.out.println("普通循环使用了:" + (System.currentTimeMillis() - start)
    + "毫秒");
  start = System.currentTimeMillis();
  //使用增强for循环,这里什么也不做
  for (int c2 : list) {
  }
  System.out.println("增强for循环使用了:" + (System.currentTimeMillis() - start)
    + "毫秒");
 }
}


上面的输出结果为:

 
黑马程序员_黑马笔记第1蛋:普通for循环和增强for循环 - hefeng.0032 - hefeng.0032的博客
很明显遍历链表时,使用增强for是非常合适的。如果注释掉LinkedList换上一句代码后,输出结果为:

黑马程序员_黑马笔记第1蛋:普通for循环和增强for循环 - hefeng.0032 - hefeng.0032的博客
 看得出遍历ArrayList数组时,使用普通for是明智的选择。
注意:增强for由于实现了迭代器(java中是Iterator)对数组和集合会先有一个拷贝,改变元素值是不能正常输出的,如果在多线程中则会出错。
<think>我们正在讨论Verilog中普通for循环generate块中的for循环的区别及适用场景。 根据之前的讨论,我们已经知道: - 普通for循环用于行为级描述(在always或initial块中),使用integer或reg作为循环变量,用于描述时序或组合逻辑的行为。 - generate for循环用于结构级描述,使用genvar作为循环变量,在编译时生成硬件结构,如重复实例化模块或生成并行赋值。 现在,我们将更详细地展开区别适用场景。 区别: 1. **循环变量类型**: - 普通for循环使用`integer`或`reg`类型变量。 - generate for循环:必须使用`genvar`类型变量。 2. **执行时机**: - 普通for循环:在仿真时执行,循环体中的语句按顺序执行(但综合工具可能会将其展开为并行硬件)。 - generate for循环:在编译时(预编译)展开,生成对应的硬件结构,每个循环迭代都独立生成硬件。 3. **位置**: - 普通for循环:只能出现在过程块(always或initial)中。 - generate for循环:出现在generate块中,且generate块可以出现在module中的任何位置(除了过程块内部)。 4. **作用**: - 普通for循环:用于描述重复的行为,例如初始化存储器、按顺序处理数据等。综合工具会尝试将其转换为并行硬件,但循环迭代次数必须是固定的。 - generate for循环:用于生成硬件结构,例如生成多个模块实例、生成多位的连线、生成参数化的硬件等。 5. **循环体**: - 普通for循环循环体可以是单条语句,也可以是多条语句(用begin-end包裹)。 - generate for循环循环体必须用begin-end块包裹,并且begin后面必须有一个名字(块名),这个名字在生成的每个实例中是唯一的。 适用场景: 1. **普通for循环适用场景**: - 需要描述重复行为,且重复次数在编译时已知。 - 例如:在初始化存储器时,用一个for循环给每个地址赋初值;在组合逻辑中,用for循环实现一个多路选择器;在时序逻辑中,用for循环实现移位寄存器等。 - 注意:普通for循环在综合后会被展开成多个相同的硬件,但综合工具会处理循环展开。 2. **generate for循环适用场景**: - 需要生成多个模块实例(例如,生成一个由多个相同子模块组成的阵列)。 - 需要生成参数化的硬件结构,例如根据参数生成不同位宽的电路。 - 需要生成并行赋值语句,且赋值数量由参数决定。 - 例如:生成一个多位加法器,其中每个位由一个全加器实例组成;生成一个多位的三态缓冲器;生成一个参数化的多路复用器树等。 示例代码: **普通for循环示例**(行为级): ```verilog // 使用普通for循环实现8位反转 always @(*) begin integer i; for (i=0; i<8; i=i+1) begin data_out[i] = data_in[7-i]; end end ``` **generate for循环示例**(结构级): ```verilog // 使用generate for循环生成8个连续赋值 genvar i; generate for (i=0; i<8; i=i+1) begin : reverse_bits assign data_out[i] = data_in[7-i]; end endgenerate ``` 注意:上面的两个例子在功能上是等价的,但实现方式不同。第一个例子在always块中,综合后生成组合逻辑;第二个例子使用generate for生成8条独立的assign语句。 另一个generate for循环实例化模块的例子: ```verilog genvar i; generate for (i=0; i<4; i=i+1) begin : adder_gen full_adder u_adder ( .a(a[i]), .b(b[i]), .cin(i==0 ? 1'b0 : adder_gen[i-1].cout), // 注意:这里使用了块名adder_gen索引来连接前一个的cout .sum(sum[i]), .cout(cout[i]) ); end endgenerate ``` 总结: - 当需要描述重复的行为(在仿真时按顺序执行,但综合后展开为并行)时,使用普通for循环(在过程块中)。 - 当需要生成重复的硬件结构(在编译时展开为多个实例)时,使用generate for循环。 另外,需要注意的是,普通for循环在综合时,循环次数必须是固定的(常量),否则无法综合。同样,generate for循环循环次数也必须是常量(由参数或常量表达式决定)。 引用[1]中的例子就是generate for循环的典型应用,它生成了4个赋值语句,每个赋值语句从输入data_in中取出2位,然后赋值给temp数组。这里循环变量i用genvar声明,循环体用begin-end包裹,并且begin后面有一个名字(test_gf)。 因此,根据需求选择合适的循环结构。 相关问题: 1. 在generate块中如何实现条件实例化(generate if/case)? 2. 为什么genvar变量不能用于仿真时的动态循环? 3. 当需要参数化的位宽处理时,generate for与函数(function)如何选择? 4. SystemVerilog对generate语法做了哪些增强?</think>### Verilog中普通for循环与generate for循环的区别及适用场景 #### 核心区别对比表 | **特性** | **普通for循环** | **generate for循环** | |------------------|-----------------------------------|--------------------------------------| | **语法位置** | 在`always`或`initial`块内部 | 在`generate`块内部 | | **循环变量** | `integer`或`reg`类型 | `genvar`类型(必须声明) | | **执行时机** | 仿真时执行(行为级) | 编译时展开(结构级) | | **硬件本质** | 描述行为逻辑(可能被综合器优化) | 生成硬件结构(直接映射为物理电路) | | **循环体要求** | 可单条语句 | 必须包含在`begin...end`块中 | | **命名要求** | 无需命名 | `begin`后必须添加唯一标识符(如`gen_block`) | | **典型应用** | 状态机、计数器、存储器初始化 | 模块实例化、参数化位宽处理、硬件阵列 | #### 适用场景详解 1. **普通for循环适用场景** - **行为级建模**:描述仿真行为(如测试平台激励生成) - **时序逻辑实现**:实现移位寄存器、计数器等 - **存储器初始化**:在`initial`块中初始化RAM/ROM ```verilog // 存储器初始化示例 reg [7:0] mem [0:255]; initial begin integer i; // 使用integer变量 for (i=0; i<256; i=i+1) mem[i] = i; // 单条语句无需begin-end end ``` - **组合逻辑简化**:多路选择器或位操作(综合后可能展开为并行逻辑) ```verilog always @(*) begin for (int i=0; i<8; i++) // SystemVerilog风格 out[i] = in[7-i]; // 位反转 end ``` 2. **generate for循环适用场景** - **硬件实例化**:批量生成重复模块(如加法器阵列) - **参数化设计**:根据参数生成可变位宽电路 - **物理结构映射**:直接对应芯片布局(如I/O缓冲器链) ```verilog // 模块实例化示例 genvar i; generate for (i=0; i<8; i=i+1) begin : adder_chain // 必须命名 full_adder u_adder ( .a(a[i]), .b(b[i]), .cin(i ? adder_chain[i-1].cout : 1'b0), // 链式连接 .sum(sum[i]), .cout() ); end endgenerate ``` - **位片操作**:参数化位选择(如引用[1]的移位操作) ```verilog generate for (i=0; i<4; i=i+1) begin : bit_slice // 必须命名 assign temp[i] = data_in[1+2*i -: 2]; // 位选择操作[^1] end endgenerate ``` #### 关键选择原则 1. **需要硬件复制时** → 用`generate for` (如生成8个独立加法器实例) 2. **需要行为描述时** → 用普通`for` (如循环等待100个时钟周期) 3. **参数化位宽处理**: - 生成物理连线 → `generate for` - 数据运算 → 普通`for`或函数 > ⚠️ **易错点**:`generate for`中的`genvar`变量**不是仿真变量**,不能在仿真中访问。例如试图用`$display`打印`genvar i`会导致编译错误[^1]。 #### 综合结果对比 ```verilog module example(input [7:0] in, output [7:0] out); // 普通for循环 → 综合为单组合逻辑块 always @(*) begin for (int i=0; i<8; i++) out[i] = in[7-i]; end // generate for → 综合为8条并行连线 genvar j; generate for (j=0; j<8; j++) begin : gen assign out[j] = in[7-j]; end endgenerate endmodule ``` - 普通`for`:综合器可能生成优化后的组合逻辑 - `generate for`:明确生成8条并行`assign`语句 [^1]:引用[1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值