perl 变量详解

http://www.perlmonks.org/?node_id=933450

use strict;
use Devel::Peek;

my $a;
Dump($a);
$a=4;
Dump($a);
$a eq "13";
Dump($a);
$a++;
Dump($a);
print $a;
Dump($a);

##</code><code>##

C:\Users\ian>perl test.pl
SV = NULL(0x0) at 0x1d9ec1c
  REFCNT = 1
  FLAGS = (PADMY)
SV = IV(0x1d9ec18) at 0x1d9ec1c
  REFCNT = 1
  FLAGS = (PADMY,IOK,pIOK)
  IV = 4
SV = PVIV(0x1d91c34) at 0x1d9ec1c
  REFCNT = 1
  FLAGS = (PADMY,IOK,POK,pIOK,pPOK)
  IV = 4
  PV = 0x1dbdf84 "4"\0
  CUR = 1
  LEN = 4
SV = PVIV(0x1d91c34) at 0x1d9ec1c
  REFCNT = 1
  FLAGS = (PADMY,IOK,pIOK)
  IV = 5
  PV = 0x1dbdf84 "4"\0
  CUR = 1
  LEN = 4
SV = PVIV(0x1d91c34) at 0x1d9ec1c
  REFCNT = 1
  FLAGS = (PADMY,IOK,POK,pIOK,pPOK)
  IV = 5
  PV = 0x1dbdf84 "5"\0
  CUR = 1
  LEN = 4
5

##</code><code>##

SV = NULL(0x0) at 0x1d9ec1c
  REFCNT = 1
  FLAGS = (PADMY)

##</code><code>##

SV = IV(0x1d9ec18) at 0x1d9ec1c
  REFCNT = 1
  FLAGS = (PADMY,IOK,pIOK)
  IV = 4

##</code><code>##

SV = PVIV(0x1d91c34) at 0x1d9ec1c
  REFCNT = 1
  FLAGS = (PADMY,IOK,POK,pIOK,pPOK)
  IV = 4
  PV = 0x1dbdf84 "4"\0
  CUR = 1
  LEN = 4

##</code><code>##

SV = PVIV(0x1d91c34) at 0x1d9ec1c
  REFCNT = 1
  FLAGS = (PADMY,IOK,pIOK)
  IV = 5
  PV = 0x1dbdf84 "4"\0
  CUR = 1
  LEN = 4

##</code><code>##

SV = PVIV(0x1d91c34) at 0x1d9ec1c
  REFCNT = 1
  FLAGS = (PADMY,IOK,POK,pIOK,pPOK)
  IV = 5
  PV = 0x1dbdf84 "5"\0
  CUR = 1
  LEN = 4

http://blob.perl.org/tpc/1998/Perl_Language_and_Modules/Perl%20Illustrated/ presents some of the details of how perl stores and keeps track of variables and their values. It is a bit more complex than the simple model presended in perldata and the commonly used terms "variable" and "value". There are several data structures used and linked to each other in the case of most variables. Depending on the history of the variable, there will be various bits of memory allocated and with more or less current values.

You can follow the evolution of $a at each step in your program by adding a few more Dump calls:

use strict; use Devel::Peek; my $a; Dump($a); $a=4; Dump($a); $a eq "13"; Dump($a); $a++; Dump($a); print $a; Dump($a);

[download]

Which produces:

C:\Users\ian>perl test.pl SV = NULL(0x0) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY) SV = IV(0x1d9ec18) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 4 SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 4 PV = 0x1dbdf84 "4"\0 CUR = 1 LEN = 4 SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 5 PV = 0x1dbdf84 "4"\0 CUR = 1 LEN = 4 SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 5 PV = 0x1dbdf84 "5"\0 CUR = 1 LEN = 4 5

[download]

The first Dump produces:

SV = NULL(0x0) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY)

[download]

At this point, the variable is declared but no value has been assigned. There is a root data structure allocated: SV, but no memory allocated to store a value: the value is undef and a NULL pointer value in the SV structure is sufficient to record this.

After assigning an integer value to the variable, Dump produces:

SV = IV(0x1d9ec18) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 4

[download]

Here an IV structure has been allocated and the assigned value, 4, has been stored in it. The pointer in the SV structure now points to the IV structure: it is not a NULL pointer any more. Flags are set to indicate that the variable now contains a valid integer value (IOK and pIOK).

Next you do a string comparison, for which perl needs to convert the variable value to a string. After this Dump shows:

SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 4 PV = 0x1dbdf84 "4"\0 CUR = 1 LEN = 4

[download]

The string value could be created, used then discarded, but instead perl updates the stored value, keeping the string value in case it might be used again. The integer value is still correct, so the variable now has two values: an integer value and a string value. Two data structures are used: the original SV and a PVIV structure which contains the integer value and a pointer to the string value. And the flags are updated to indicate that there are valid integer and string values.

Your next operation is to increment $a. This is an operation on its integer value. In this case, perl is frugal and does only enough work to record the result. The integer value is changed but the string value is not changed. Rather, the flags indicating a valid string value are turned off. After this, Dump produces:

SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 5 PV = 0x1dbdf84 "4"\0 CUR = 1 LEN = 4

[download]

Note that perl does not bother to change the PVIV structure back to an IV structure. The latter is smaller but the saving of memory would be tiny - not enough to justify the work. So, the PVIV structure remains, and it still points to the memory allocated to hold the string value, which still has the old, but no longer correct string value of the variable. It‘s OK that the string value is incorrect because the POK and pPOK flags are off, so the value will not be used. This wastes some memory, but saves some CPU.

Then you print the value of $a. Again, a string value is needed. While the PVIV structure has a pointer to a string value, the POK and pPOK flags in the SV are off, so this value isn‘t used. Instead, perl again converts the current integer value to a string and prints that correct value. And, again, perl saves this value in case it might be used again. So, after printing Dump produces:

SV = PVIV(0x1d91c34) at 0x1d9ec1c REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 5 PV = 0x1dbdf84 "5"\0 CUR = 1 LEN = 4

[download]

Again there are both integer and string values, and they are current and consistent. The IOK, POK, pIOK and pPOK flags are all set so that in subsequent operations these value might be used.

Note also that the new string value is in the same bit of memory that the original string value was in. No additional memory was needed, so no new memory was allocated. The original memory was re-used. A lot of work has gone into minimizing expensive operations for the sake of performance.

You might try extending your program, assigning a long string value to $a and then dumping it again. If you did, you would see that the same SV and PVIV structures were in use but the IOK and pIOK flags were off and the integer value in the PVIV remained unchanged and the long string was contained in newly allocated memory, as it wouldn‘t fit in the block originally allocated to hold the previous single character value.

时间: 2024-10-29 03:04:55

perl 变量详解的相关文章

PATH环境变量和CLASSPATH环境变量详解

大凡装过JDK的人都知道要安装完成后要设置环境变量,可是为什么要设置环境变量呢?环境变量有什么作用? 1)PATH详解: 计算机安装JDK之后,输入“javac”“java”之类的命令是不能马上被计算机正确执行的,因为计算机不知道到哪里去找这两个命令. 计算机如何查找命令呢?Windows操作系统根据PATH环境变量来查找命令.PATH环境变量的值是一系列路径,Windows操作系统将在这一系列的路径中依次查找命令,如果能找到这个命令,则该命令是可执行的:否则将出现“‘XXX’不是内部命令或外部

mysql show variables系统变量详解

mysql系统变量详解 mysqld服务器维护两种变量.全局变量影响服务器的全局操作.会话变量影响具体客户端连接相关操作. 服务器启动时,将所有全局变量初始化为默认值.可以在选项文件或命令行中指定的选项来更改这些默认值.服务器启动后,通过连接服务器并执行SET GLOBAL var_name语句可以更改动态全局变量.要想更改全局变量,必须具有SUPER权限. 服务器还为每个客户端连接维护会话变量.连接时使用相应全局变量的当前值对客户端会话变量进行初始化.客户可以通过SET SESSION var

java环境变量详解---找不到或无法加载主类

刚学java,配置好环境变量之后,在DOS下却运行java小程序却始终出现"找不到或无法加载主类"然后返回配置环境变量折腾了好久,查看书籍.网上的资料,最终OK了!安装Eclipse始终出现 "could not find Java SE runtime environment"."could not find java dll"这样的问题,按照网上提供的资料却始终解决不了问题,最后将最新版本的Eclipse换了,才可以用. 以下是安装JDK的总

Shell学习之Bash变量详解(二)

Shell学习之Bash变量详解 目录 Bash变量 Bash变量注意点 用户自定义变量 环境变量 位置参数变量 预定义变量 Bash变量 用户自定义变量:在Bash中由用户定义的变量. 环境变量:这种变量中主要保存和系统操作环境相关的数据. 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的. 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的. Bash变量注意点 1.变量名称可以由字母.数字和下划线组成,但是不能以数字

【转】asp.net core环境变量详解

环境变量详解 Windows操作系统的环境变量在哪设置应该都知道了. Linux(centos版本)的环境变量在/etc/profile里面进行设置.用户级的环境变量在其它文件里面,不多说了,有兴趣的可以网上查下. 当我们的应用程序发布到生产环境时,如果用到了环境变量,就需要对服务器操作系统的环境变量进行设置.这里只是进行提前说明. 设置环境变量 环境变量可以在launchSettings.json文件里面设置,也可以右键项目->属性->调试->环境变量进行设置.这两种方式的内容是同步的

多线程之 Final变量 详解

原文: http://www.tuicool.com/articles/2Yjmqy 总结: Final 变量在并发当中,原理是通过禁止cpu的指令集重排序(重排序详解http://ifeve.com/java-memory-model-1/ http://ifeve.com/java-memory-model-2/),来提供现成的课件性,来保证对象的安全发布,防止对象引用被其他线程在对象被完全构造完成前拿到并使用. 与Volatile 有相似作用,不过Final主要用于不可变变量(基本数据类型

Perl中的特殊内置变量详解

#!/usr/bin/perl -w @array = qw(a b c d); foreach (@array) { print $_," "; } 例子的作用就是定义一个数组并把其中的元素打印出来,这里需要注意的是foreach循环部分,foreach循环的标准格式应该是: foreach $element (@array){ ...... } 其中数组@array将其中的元素依次赋值给$element,但是在上面那个程序中,我并没有这样做,在程序中,我就使用到了perl中内置的一

Linux下Bash编程之变量详解(一)

1.语言分类: 1.1.静态语言:编译型语言 强类型:变量在使用前,必须事先声明,甚至还需要初始化: 编写的程序事先转换成可执行格式 代表有:C.C++.JAVA.C# 动态语言:解释型语言 弱类型:变量用时声明,甚至不区分类型: 编写的程序边解释边执行 代表有: PHP.SHELL.python.perl 1.2.面向过程编程语言:代表有 Shell, C 1.3.面向对象编程语言: 代表有 JAVA, Python, perl, C++ 结论:shell属于弱类型编程语言 2.shell编程

tomcat Win10 配置环境变量详解

在Win10系统总该如何配偶之tomcat 环境变量?今天win10之家给大家带来了关于win10系统中配置tomcat环境的操作方法.在配置之前我们需要做以下几点: 步骤:安装和配置好了Java 的jdk (单机版) 1.下载Tomcat,解压到短一些路径的英文文件夹中,如:D:\Program Files\Tomcat : 2.在开始按钮单击鼠标右键,选择[系统]如图:www.w10zj.com 3.接着点击"高级系统设置": 4.点击"高级"选项卡,在右下角点