Verilog学习(3)initial,always,task,function,常见系统任务

2023-10-25 12:50

本文主要是介绍Verilog学习(3)initial,always,task,function,常见系统任务,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

结构说明语句

Verilog中任何过程模块都属于以下四种结构的说明语句:initial说明语句,always 说明语句,task说明语句,function说明语句。

一个程序模块可以有多个initial和always 过程块。每个initial,always说明语句再仿真开始同时执行。initial 执行一次,always语句不断重复活动直到仿真结束。但always是否运行看触发条件是否满足,满足运行一次,再次满足执行一次,直到仿真结束。

task 和 function 语句可以再程序模块中的一处或多处调用

initial语句

// 对存储器变量赋初始值
initialbeginareg = 0;                // 初始化寄存器for(index = 0;index <size;index=index+1)memory[index] = 0;   // 初始化一个memoryend

仿真开始时对各变量初始化,这个过程不需要仿真时间 0ns内初始化工作就完成了。一个模块可以有多个initial语句,都是并行的,常用于测试文件和虚拟模块的编写,用来产生仿真测试信号和设置信号记录等仿真环境。

always语句

格式为: always <时许控制> <语句>。always语句由于不断活动的特性,一定要和一定的时许结合,没有时许控制这个always语句就会使仿真器产生死锁。

always areg = ~areg  // 0延迟的无限循环跳变过程,发生仿真死锁always #half_period areg = ~areg; // 生成一个周期为period(=2*half_period) 的无限延续的信号波形,//常用于描述时钟信号,并作为激励信号测试设计的电路。reg[7:0] conter;
reg tick;
always @(posedge areg)begintick = ~tick;counter = counter + 1;end
// 每当areg信号的上升沿出现将tick信号反向,counter加一

always 的时间控制可以是沿触发也可以是电平触发,可以检测单个信号也可以多个信号,中间用or连接。多个电平触发的always块,一个发生变换就会执行一次。沿触发的always块常用于描述时序行为。电平触发的常用于描述组合逻辑的行为。一个模块可以有多个always块,并行执行。

//有异步复位的电平敏感锁存器
always @ ( reset  or  clock  or  d ) // or 也可以用 , 代替 alwyas @(reset, clock, d)//等待复位信号reset 或 时钟信号clock 或 输入信号d 的改变
begin                if ( reset )         //若 reset 信号为高,把q置零q = 1 'b0 ;else  if ( clock )   //若clock 信号为高,锁存输入信号dq = d ;
end//用reset异步下降沿复位,clk正跳变沿触发的D寄存器
always @ ( posedge clk , negedge reset )  //注意:使用逗号来代替关键字orif (! reset )q <= 0 ;else q <= d ;

Verilog提供了另外两个特殊符号 @ * , @ (*),表示对 后面语句块中所有输入变量的变化是敏感的。解决输入变量很多的情况。

//用or 操作符的组合逻辑块
//编写敏感列表很繁琐并且容易漏掉一个输入
always @ ( a or b or c or d or e or f or g or h or p or m )beginout1 = a ?  b + c  :  d + e ;out2 = f ?  g + h  :  p + m ;end//不用上述方法,用符号 @(*) 来代替,可以把所有输入变量都自动包括进敏感列表。
always @ ( * )       beginout1 = a ?  b + c  :  d + e ;out2 = f ?  g + h  :  p + m ;end

之前的需要等待信号值变化或事件触发,同时也可以用另一种形式表示电平敏感时许控制,即后面的语句和语句块需要等待某个条件为真才执行。使用wait表示等待电平敏感条件为真。

alwayswait(count_enable)  #20 count = count +1;

仿真器连续监视conunt_enable 的值,为0不执行后面的,仿真停顿,值为1,则再20个时间单位后执行,如果count_enable始终为1,count没过20个时间单位加一。

task 和function说明语句

这俩分别用来定义任务和函数,可以把一个很大的程序模块分解成许多较小的任务和函数便于理解和调试。不同点:

  • 函数只能与主模块共用一个仿真时间单位,任务可以自定义自己的仿真时间单位
  • 函数不能启动任务,任务可以启动其他任务和函数
  • 函数至少有一个输入变量,任务可以没有或有多个任何类型的变量
  • 函数返回一个值,任务不返回值

函数就是返回一个值响应输入,任务支持多目的,可以计算多个结果值,这些结果值只能通过被调用的任务的输出或者总线端口送出。

func(a,b)   // 任务,通过输出端口的变量输出
b = func(a)  // 函数,带返回值

task说明语句

定义了传递给任务的变量值和接受变量,可以用一条语句启动任务,任务完成控制传回启动过程。如果任务内部有定时控制,启动时间可以与控制返回时间不同,任务可以启动其他任务,数量没有限制。不管多少任务启动,只有所有启动任务完成,控制才能返回。

task 任务名;端口及数据类型声明语句语句
endtask // 描述红绿黄交通灯行为的Verilog模块,其中使用了任务。该模块只是一个行为模块不能综合成电路网表。
module traffic_lights;
// 一个模块如果和外部环境没有交互,则可以不用声明端口列表。(端口是模块与外界交互的接口)reg  clock, red, amber, green;parameter  on=1, off=0, red_tics=350,amber_tics=30,green_tics=200;//交通灯初始化initial	red=off;initial	amber=off;initial	green=off;//交通灯控制时序,always 语句是重复执行的alwaysbeginred=on;		//开红灯light(red,red_tics);	//调用等待任务green=on;		//开绿灯light(green,green_tics);	//等待amber=on;		//开黄灯light(amber,amber_tics);	//等待end//定义交通灯开启时间的任务task  light;output  color;input[31:0] tics;beginrepeat(tics) @(posedge clock);//等待tics个时钟的上升沿color=off;//关灯endendtask//产生时钟脉冲的always块alwaysbegin#100 clock=0;#100 clock=1;end
endmodule

function说明语句

格式:
function 返回值类型或范围(可选,默认返回一位寄存器类型数据) 函数名端口说明语句变量类型说明语句begin语句end
endfunctionfunction [7:0] getbyte;input [15:0] address;begin<说明语句>		//从地址字中提取低字节的程序getbyte = result_expression;   //把结果赋予函数的返回字节end
endfunction

函数的定义蕴含声明与函数同名,函数内部的寄存器,也就是会生成定义中<返回值类型或范围> 一致的寄存器。函数的定义把函数返回值所赋值寄存器的名称初始化为与函数同名的内部变量

word = control ? {getbyte(a),getbyte(b)} : 0
// 函数调用,这里调用两次函数getbyte,将函数产生的值进行位拼接生成一个字。这里getbyte被赋予的值就是函数的返回值

函数定义不能包含任何时间控制语句,不能启动任务,定义时至少一个输入变量,定义中必须有一条赋值语句给函数中的一个内部变量赋以函数的结果值,这个内部变量名字与函数名相同

module  tryfact;   // 阶乘//函数的定义-------------------------------function[31:0] factorial;input[3:0]operand;reg[3:0]index;beginfactorial = 1;  //  0的阶乘为1, 1的阶乘也为1for(index=2; index<=operand; index=index+1)factorial = index * factorial;  // 返回值endendfunction//函数的测试-------------------------------------reg[31:0]result;reg[3:0]n;initialbeginresult=1;for(n=2;n<=9;n=n+1)begin$display("Partial result n= %d result= %d", n, result);result = n * factorial(n)/((n*2)+1);end$display("Finalresult=%d",result);end
endmodule // 模块结束

例子:奇偶校验,位移寄存器,数码管


// 偶校验位计算,返回校验值,注意HDL是并行的
/*
奇偶校验(Parity Check)是一种校验代码传输正确性的方法。
根据被传输的一组二进制代码的数位中“1”的个数是奇数或偶数来进行校验。
采用奇数的称为奇校验,反之,称为偶校验。采用何种校验是事先规定好的。
通常专门设置一个奇偶校验位,用它使这组代码中“1”的个数为奇数或偶数。
若用奇校验,则当接收端收到这组代码时,校验“1”的个数是否为奇数,从而确定传输代码的正确性。
*/
// 定义一个模块,其中包含能计算偶校验位的函数(calc_parity)
module parity;reg [31:0] addr;reg parity;initialbeginaddr = 32'h3456_789a;#10 addr = 32'hc4c6_78ff;#10 addr = 32'hff56_ff9a;#10 addr = 32'h3faa_aaaa;end//每当地址值发生变化,计算新的偶校验位 always @(addr)beginparity = calc_parity(addr);   //第一次启动校验位计算函数 calc_parity,赋值给寄存器变量$display("Parity calculated = %b", calc_parity(addr) ); // 第二次启动校验位计算函数 calc_parity,返回值直接使用系统任务display显示end//定义偶校验计算函数 function calc_parity; input [31:0] address;begin//适当地设置输出值,使用隐含的内部寄存器calc_parity // ^a操作就是将a中的每一位按位逐一进行异或,例如a=4'b1010,则b=1^0^1^0=1,// 由此可以判断a中为1的位数是奇数还是偶数,是一个便捷的操作。calc_parity = ^address;  //返回所有地址位的异或值 endendfunctionendmodulefunction  calc_parity (input [31:0] address);     // c风格的声明函数变量begin//适当地设置输出值,使用隐含的内部寄存器calc_parity calc_parity = ^address;  //返回所有地址位的异或值 end
endfunction// 定义一个包含移位函数的模块 ,移位寄存器
module shifter;// 左/右 移位寄存器 `define LEFT_SHIFT      1'b0`define RIGHT_SHIFT     1'b1reg [31:0] addr, left_addr, right_addr;reg control;//每当新地址出现时就计算右移位和左移位的值  always @(addr)begin//调用下面定义的具有左右移位功能的函数 left_addr = shift(addr, `LEFT_SHIFT);right_addr = shift(addr, `RIGHT_SHIFT);end//定义移位函数,其输出是一个32位的值function [31:0] shift;input [31:0] address;input control;begin//根据控制信号适当地设置输出值 shift = (control == `LEFT_SHIFT) ? (address << 1) : (address >> 1);                       endendfunctionendmodule/*用信号 abcdefg 来控制光亮控制端,用信号 csn 来控制片选,
4 位 10 进制的数字个十百千位分别用 4 个 4bit 信号 
single_digit, ten_digit, hundred_digit, kilo_digit 来表示*/
module digital_tube  //  4 位 10 进制的数码管译码器(input             clk ,input             rstn ,input             en ,input [3:0]       single_digit ,input [3:0]       ten_digit ,input [3:0]       hundred_digit ,input [3:0]       kilo_digit ,output reg [3:0]  csn , //chip select, low-available 低电平有效output reg [6:0]  abcdefg        //light control);reg [1:0]            scan_r ;  //scan_ctrlalways @ (posedge clk or negedge rstn) beginif(!rstn)begin    // 复位csn            <= 4'b1111;abcdefg        <= 'd0;scan_r         <= 3'd0;endelse if (en) begin  // 使能case(scan_r)2'd0:beginscan_r    <= 3'd1;   // 逐位赋值csn       <= 4'b0111;     //select single digitabcdefg   <= dt_translate(single_digit);end2'd1:beginscan_r    <= 3'd2;csn       <= 4'b1011;     //select ten digitabcdefg   <= dt_translate(ten_digit);end2'd2:beginscan_r    <= 3'd3;csn       <= 4'b1101;     //select hundred digitabcdefg   <= dt_translate(hundred_digit);end2'd3:beginscan_r    <= 3'd0;csn       <= 4'b1110;     //select kilo digitabcdefg   <= dt_translate(kilo_digit);endendcaseendend/*------------ translate function -------*/function [6:0] dt_translate;input [3:0]   data;begincase(data)4'd0: dt_translate = 7'b1111110;     //number 0 -> 0x7e4'd1: dt_translate = 7'b0110000;     //number 1 -> 0x304'd2: dt_translate = 7'b1101101;     //number 2 -> 0x6d4'd3: dt_translate = 7'b1111001;     //number 3 -> 0x794'd4: dt_translate = 7'b0110011;     //number 4 -> 0x334'd5: dt_translate = 7'b1011011;     //number 5 -> 0x5b4'd6: dt_translate = 7'b1011111;     //number 6 -> 0x5f4'd7: dt_translate = 7'b1110000;     //number 7 -> 0x704'd8: dt_translate = 7'b1111111;     //number 8 -> 0x7f4'd9: dt_translate = 7'b1111011;     //number 9 -> 0x7bendcaseendendfunctionendmodule

自动递归函数

Verilog的函数不能递归调用。若在函数声明时使用了关键字 automatic,那么该函数将称为自动的或可递归的,即仿真器为每一次函数调用动态的分配新的地址空间,每个函数调用对各自的地址空间进行操作,避免了对同一个地址空间操作造成结果不确定。因此自动函数中声明的局部变量不能通过层次名进行访问,而自动函数本身可以通过层次名进行调用,。

//用函数的递归调用定义阶乘计算
module top ;...//定义自动(递归)函数function  automatic  integer  factorial ;    // 返回类型 整形input  [ 31 : 0 ]  oper ;integer  i ;beginif ( operand >= 2 )factorial = factorial ( oper - 1 ) * oper ;  //递归调用else factorial = 1 ;endendfunction//调用该函数integer result ;initial beginresult = factorial ( 4 ) ; // 调用4的阶乘$display ( " Factorial of 4 is % 0d ", result ) ;   // 显示24end............
endmodule 

常量函数与带符号函数

一个带有某些限制的常规函数,常数函数是指在仿真开始之前,在编译期间就计算出结果为常数的函数。常数函数不允许访问全局变量或者调用系统函数,但是可以调用另一个常数函数。

这种函数能够用来引用复杂的值,因此可用来代替常量。

带符号函数返回值可以作为带符号数进行计算

parameter    MEM_DEPTH = 256 ;
reg  [logb2(MEM_DEPTH)-1: 0] addr ; //可得addr的宽度为8bitfunction integer     logb2;input integer     depth ;//256为9bit,我们最终数据应该是8,所以需depth=2时提前停止循环for(logb2=0; depth>1; logb2=logb2+1) begindepth = depth >> 1 ;end
endfunctionmodule top ;... ...////function  signed [ 63 : 0 ]  compute _signed (  input [ 63 : 0 ]  vector ) ;... ...... ...endfunction//if ( compute_signed (vector)  <  - 3 )begin... ...end... ... 
endmodule

系统任务

$display $write 任务

这俩个函数和系统任务的作用就是输出信息,将输出列表以固定格式输出。前者自动的在输出后进行换行,$write 不同,在一行里输出多个信息就用write。可以再%write 中加入\n 换行。
在这里插入图片描述

module  disp;initialbegin$display("\\\t%%\n\"\123");end
endmodule输出结果为
\%
"S
//从上面的这个例子中可以看到一些特殊字符的输出形式(八进制数123就是字符S)。module disp;reg[31:0] rval;pulldown(pd);initialbeginrval=101;$display("rval=%h hex %d decimal", rval, rval);$display("rval=%o otal %b binary", rval, rval);$display("rval has %c ascii character value",rval);$display("pd strength value is %v",pd);$display("current scope is %m");$display("%s is ascii value for 101",101);$display("simulation time is %t",$time);end
endmodule其输出结果为:
rval=00000065 hex 101 decimal
rval=00000000145 octal 00000000000000000000000001100101 binary
rval has e ascii character value
pd strength value is StX
current scope is disp
e is ascii value for 101
simulation time is 0

$display 中,输出列表中数据显示宽度是自动按照输出格式进行调整的。显示数据时,经过格式转换后,总是用表达式的最大可能值所占的位数显示表达式的值。例如一个位宽12的表达式,按照十六进制输出输出结果占三个字符的位置,按照十进制输出,输出结果占4个字符的位置。这时应为这个表达式最大可能值为FFF,4095(十进制).

$display("d=%0h a=%0h",data,addr)  // 再%和进制符号间插入一个0自动调整显示输出数据宽度的方式,这样总是用最少的位数显示。module printval;
reg[11:0]r1;
initialbeginr1=10;$display("Printing with maximum size=%d=%h",r1,r1);$display("Printing with minimum size=%0d=%0h",r1,r1);end
enmodule
输出结果为:
Printing with maximum size=10=00a:
printing with minimum size=10=a;

输出列表中的表达式包含不确定值或高阻值,输出遵循:

  • 输出格式十进制下,所有位是不定值输出x,都是高阻值输出z,部分不定值、高阻值输出X,Z。
  • 十六进制八进制,4位二进制一组代替一位十六进制,三位二进制代替八进制。值均为不定值/高阻值,输出小写x,z ,部分输出大写。
$display("%d",1'bx);  									输出 x
$display("$h",14'bx0_1010);								输出 xxXa,14位分4组
$display("%h%o",12'b001x_xx10_1x01,12'b001_xxx_101_x01); 输出 XXX1x5X

文件输出

Verilog的结果通常输出到标准输出和文件verilog.log文件中,也可以重定位到选择的文件

  1. 打开文件 句柄= $fopen(“name”); 返回一个叫多通道描述符的32位值。只有一位设置为1.标准输出最低位为1,也被称为通道0,一直开放。以后$foren 每一次调用就会打开一个新通道,返回一个设置了第1位,2位到32位描述符的第30位。31位保留。

多通道描述符的优点在于可以有选择地同时写多个文件。

//多通道描述符 
integer  handle1, handle2, handle3;  //整型数为 32 位
//标准输出是打开的; descriptor = 32'h0000_0001  ( 第0位置1)
initial
beginhandle1 = $fopen("file1.out");  //handle1 = 32'h0000_0002 (bit 1 set 1)handle2 = $fopen("file2.out");  //handle2 = 32'h0000_0004 (bit 2 set 1)handle3 = $fopen("file3.out");  //handle3 = 32'h0000_0008 (bit 3 set 1)
end
  1. 写文件,$fdisplay, $fmonitor,$fwrite,$fastrobe 都用于写。$fdisplay( 文件描述符, 变量/信号名/字符串)
    文件描述符可以是一个多通道描述符或者多个文件句柄的按位组合。会把输出写到文件描述符中值为1的位相关联的所有文件中。
//写到文件中去
integer desc1, desc2, desc3 ; // 三个文件的描述符
initial
begindesc1 = handle1 | 1;  //按位或;  desc1 = 32'h0000_0003   $fdisplay(desc1, "Display 1"); //写到文件file1.out和标准输出stdoutdesc2 = handle2 | handle1;  //desc2 = 32 'h0000_0006$fdisplay(desc2, "Display 2");  //写到文件file1.out和file2.outdesc3 = handle3 ;   //desc3 = 32'h0000_0008$fdisplay(desc3, "Display 3");  //只写到文件file3.out  
end
  1. 关闭文件 f c l o s e ‘ fclose ` fclosefclose(handle1);` 文件关闭,多通道描述符中相应位设置为0.

显示层次

通过任何显示任务,比如%display, $write 等任务中的 %m 选项可以显示任何级别的层次,这个有用。比如一个模块中的毒功而实例执行同一段代码,%m选项会区分那个模块示例在输出。%m选项不需要参数。

//显示层次信息 
module  M;initial$display("Displaying in %m");
endmodule//调用模块M
module top;M  m1 ( );M	  m2 ( );M  m3 ( );endmodule仿真输出如下所示:
Displaying in top.m1
Displaying in top.m2
Displaying in top.m3

可以显示全层次路径名,包括模块示例,任务,函数,和命名块。

选通显示

$strobe ,与$display类似,$display与其他语句是在同一时间执行,这些执行顺序是不确定的,但$strobe总是在同时刻其他赋值语句完成后才执行。提供了一种同步机制,可以确保同一时钟沿赋值的其他语句执行完成才显示数据。

//选通显示
always @ (posedge clock)
begina = b ;c = d ;
endalways @ (posedge clock)$strobe (“Displaying a = %b,  c = % b” , a , c );  //显示正跳变沿时刻的值//时钟上升沿的值在语句a = b和c = d执行完之后才显示。
//如果使用$display,$display可能在语句a = b和c = d之前执行,结果显示不同的值。

值变转储文件

值变转储文件VCD 是一个ASCII文件,包含仿真时间,范围,与信号的定义以及仿真运行过程中信号值的变化等信息。设计中的所有信号或选定的信号集合在仿真过程中都可以写入VCD文件。后处理工具可以把VCD作为输入把层次信息,信号值,信号波形显示出来。也可以使用后处理工具进行调试,分析,验证仿真输出结果。

$dumpvars 选择要转储的模块示例或模块实例信号, $dumpfile选择VCD文件名称,$dumpon,$dumpoff 选择转储过程的起点,终点,$dumpall 选择生成监测点。前俩通常在仿真开始时指定,后面三个在仿真过程中控制转储过程。

//指定VCD文件名。若不指定VCD文件,则由仿真器指定一缺省文件名
initial$dumpfile (“ myfile.dmp”) ;  //仿真信息转储到myfile.dmp文件// 转储模块中的信号
initial $dumpvars ;   //没有指定变量范围,把设计中全部信号都转储
initial$dumpvars ( 1, top ) ;    //转储模块实例 top中的信号
//数1 表示层次的等级, 只转储top下第一层信号
//即转储top模块中的变量,而不转储在top中调用
//模块中的变量
initial $dumpvars (2, top.m1) ;      //转储top.m1模块下两层的信号initial $dumpvars (0, top.m1) ;     ///数0 表示转储top.m1模块下面各个层的所有信号//启动和停止转储过程
initialbegin$dumpon ;     //启动转储过程#100000 $dumpoff ;  //过了100000个仿真时间单位后,停止转储过程end//生成一个检查点,转储所有VCD变量的现行值。
initial $dumpall ; 

具有图形显示功能的后处理工具是仿真调试过程中重要组成部分,另外选择真正需要检测的信号进行转储,减小VCD文件大小。

其他

在这里插入图片描述

这篇关于Verilog学习(3)initial,always,task,function,常见系统任务的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/282684

相关文章

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Spring定时任务只执行一次的原因分析与解决方案

《Spring定时任务只执行一次的原因分析与解决方案》在使用Spring的@Scheduled定时任务时,你是否遇到过任务只执行一次,后续不再触发的情况?这种情况可能由多种原因导致,如未启用调度、线程... 目录1. 问题背景2. Spring定时任务的基本用法3. 为什么定时任务只执行一次?3.1 未启用

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置

java常见报错及解决方案总结

《java常见报错及解决方案总结》:本文主要介绍Java编程中常见错误类型及示例,包括语法错误、空指针异常、数组下标越界、类型转换异常、文件未找到异常、除以零异常、非法线程操作异常、方法未定义异常... 目录1. 语法错误 (Syntax Errors)示例 1:解决方案:2. 空指针异常 (NullPoi

如何使用Python实现一个简单的window任务管理器

《如何使用Python实现一个简单的window任务管理器》这篇文章主要为大家详细介绍了如何使用Python实现一个简单的window任务管理器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 任务管理器效果图完整代码import tkinter as tkfrom tkinter i

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa