返回列表 发帖
本帖最后由 batman 于 2011-4-23 11:21 编辑

再次测试(测试前猜想变量减少时,变量的内存存储开始地址不会改变)
代码:
@echo off&setlocal enabledelayedexpansion
del /q db-*.txt
call :lp 1 100 random
call :lp 10 20
del /q db
goto :eof
:lp
for /l %%a in (%1,1,%2) do set "_%%a=!%3!"
(echo d2cl2
echo q
echo,
)>db
(for /f "skip=1 tokens=2,3" %%a in ('debug^<db') do (
     echo d%%b%%a:0380&echo q&echo,
))>tem
del /q db&ren tem db
debug<db>db-%1.txt
start db-%1.txtCOPY
db-1.txt
-d0DCC:0380
0DCC:0380  00 5F 31 3D 31 34 37 36-32 00 5F 31 30 3D 35 35   ._1=14762._10=55
0DCC:0390  37 37 00 5F 31 30 30 3D-32 31 31 35 33 00 5F 31   77._100=21153._1
0DCC:03A0  31 3D 37 37 35 35 00 5F-31 32 3D 31 35 35 38 36   1=7755._12=15586
0DCC:03B0  00 5F 31 33 3D 31 30 38-31 00 5F 31 34 3D 38 38   ._13=1081._14=88
0DCC:03C0  34 39 00 5F 31 35 3D 34-34 35 31 00 5F 31 36 3D   49._15=4451._16=
0DCC:03D0  31 32 39 34 35 00 5F 31-37 3D 32 35 37 33 35 00   12945._17=25735.
0DCC:03E0  5F 31 38 3D 31 33 30 31-31 00 5F 31 39 3D 32 37   _18=13011._19=27
0DCC:03F0  39 39 35 00 5F 32 3D 31-37 31 31 33 00 5F 32 30   995._2=17113._20
-qCOPY
db-10.txt
-d0DCC:0380
0DCC:0380  00 5F 31 3D 31 34 37 36-32 00 5F 31 30 30 3D 32   ._1=14762._100=2
0DCC:0390  31 31 35 33 00 5F 32 3D-31 37 31 31 33 00 5F 32   1153._2=17113._2
0DCC:03A0  31 3D 32 37 37 36 30 00-5F 32 32 3D 33 37 36 35   1=27760._22=3765
0DCC:03B0  00 5F 32 33 3D 31 33 30-37 35 00 5F 32 34 3D 37   ._23=13075._24=7
0DCC:03C0  35 38 38 00 5F 32 35 3D-31 31 31 30 36 00 5F 32   588._25=11106._2
0DCC:03D0  36 3D 32 33 36 38 35 00-5F 32 37 3D 31 32 37 38   6=23685._27=1278
0DCC:03E0  39 00 5F 32 38 3D 32 30-33 30 31 00 5F 32 39 3D   9._28=20301._29=
0DCC:03F0  32 31 39 35 31 00 5F 33-3D 31 35 32 32 00 5F 33   21951._3=1522._3
-qCOPY
可见当变量减少时(部分变量被清空),其实就是对已有变量进行读取操作时,内存确实不会重新洗牌。
***共同提高***

TOP

8# plp626


当然了,set /a 要把字符串类型转换成数字类型。这里是快了,如果后面的这个变量要参与数学计算的话,通过set设置的字符串还是需要再次转换成数字类型的,这样时间就扯平了。变量一般只设置一次,但是这个变量可能参与多次数学计算的话,很明显set /a  设置的数字类型将更有优势。

TOP

89# applba


批处理存储在内存的变量是否有数据类型之分呢?这又是一个分歧点,有得闹了

TOP

人呢人呢?
这种版主级的舌战正是我所乐见的,向往了这么久,难得碰到一两次,怎么才讨论了一晚上+一上午就停火了...
问题还没解决呐...疑点还很多,举几个例子:
一、究竟是一张表还是N张表?子疑点:
1、系统变量与用户变量的关系,当用户变量覆盖系统变量时,系统变量去哪了?
2、setlocal后的变量是否和setlocal前的变量放在一张表里,并且一起按ansi排序呢?
二、变量存储时是否区分数据类型?
三、只感觉还有些问题迷迷糊糊,但没能抓住思绪,因此下文待续...

TOP

本帖最后由 cjiabing 于 2011-4-23 13:15 编辑
80# batman


1,用来说明微软为什么使用全字符ANSI来排列变量名。
2,命令解释器进内存中的环境变量区间是如何匹配的,是拿着变量名一个一个的遍历所有变量名来比较,还是按着ANSI顺序逐字比较变量名。
hanyeguxing 发表于 2011-4-23 10:20

      还是兄科学发展观学得好,不懂他们鼓捣出什么“真理”出来没有!~
      既然是“变量机制”,至少得出个有现实意义的结论,好指导我们平时怎么设置变量。
      比如用 !var! 还是用 %var% ,用不同的变量还是用同一个变量,用%abc% 顺序的,还是%zijizuodepichulibianliangjizhi%冗长颠倒的变量,用变量还是用临时文件,用多个不同变量,还是用同一个变量……
      再问深一点的:变量是怎么来的?它的作用是什么?它的运行机制是什么?它在内存中是怎么样工作的?变量是如何赋值和如何取消的?微软是怎么解释的?微软是怎么使用变量的?变量与什么有关?变量的极限是什么?有没有最佳和最差变量?有没有系统内部通用变量?怎么区分和联系各种变量?批处理的变量是否可以超出cmd.exe?计算机编码和进制对变量有什么影响?变量在解释器中如何解释?……
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

本帖最后由 batman 于 2011-4-23 13:44 编辑

还是测试说明问题,但也带来了新问题。。。。
代码:
@echo off&setlocal enabledelayedexpansion
for /l %%a in (1,1,100) do set "d=!d!&echo d"
call :lp _str a
call :lp _str b setlocal endlocal
call :lp _str s
del /q db&pause
goto :eof
:lp
%3
if "%2" neq "s" set "%1=%2"
(echo d2cl2
echo q
echo,
)>db
(for /f "skip=1 tokens=2,3" %%a in ('debug^<db') do (
     echo d%%b%%a:0000%d%&echo q&echo,
))>tem
del /q db&ren tem db
for /f "delims=" %%a in ('debug^<db^|findstr /i "%1="') do echo %%a
echo,
%4COPY
结果:
0DBD:0640  5F 53 54 52 3D 61 00 42-4C 41 53 54 45 52 3D 41   _STR=a.BLASTER=A
0DBD:0640  5F 53 54 52 3D 62 00 42-4C 41 53 54 45 52 3D 41   _STR=b.BLASTER=A
0DBD:0640  5F 53 54 52 3D 61 00 42-4C 41 53 54 45 52 3D 41   _STR=a.BLASTER=A
Press any key to continue . . .COPY
上面的测试表明,setlocal前以及setlcoal-endlocal中以及endlocal后_str变量在内存中储存的地址没有改变(至少是开始值没有改变)。同时说明了cmd中为什么变量名不分大小写,因为不管变量中的字符是不是大小写,内存中统一是以大写的字符储存的变量。但这里又有一个问题了,既然内存中只会储存一个名为_str的变量,那么endlocal后这个变量的值又是怎么恢复为前面的值的,难道还有一个临时储存变量的地方?
***共同提高***

TOP

测试系统变量:
@echo off&setlocal enabledelayedexpansion
for /l %%a in (1,1,100) do set "d=!d!&echo d"
call :lp os
call :lp os a setlocal endlocal
call :lp os
del /q db&pause
goto :eof
:lp
%3
if "%2" neq "" set "%1=%2"
(echo d2cl2
echo q
echo,
)>db
(for /f "skip=1 tokens=2,3" %%a in ('debug^<db') do (
     echo d%%b%%a:0000%d%&echo q&echo,
))>tem
del /q db&ren tem db
for /f "delims=" %%a in ('debug^<db^|findstr /i "%1="') do echo %%a
echo,
%4COPY
0DBD:03F0  52 4F 43 45 53 53 4F 52-53 3D 32 00 4F 53 3D 57   ROCESSORS=2.OS=W
0DBD:03F0  52 4F 43 45 53 53 4F 52-53 3D 32 00 4F 53 3D 61   ROCESSORS=2.OS=a
0DBD:03F0  52 4F 43 45 53 53 4F 52-53 3D 32 00 4F 53 3D 57   ROCESSORS=2.OS=W
Press any key to continue . . .COPY
系统变量os在setlcoal-enlocal中去哪里了?,假如将os改成path,运行结果如下:
0DBD:0400  69 6E 64 6F 77 73 5F 4E-54 00 50 41 54 48 3D 43   indows_NT.PATH=C
'debug' is not recognized as an internal or external command,
operable program or batch file.
'debug' is not recognized as an internal or external command,
operable program or batch file.
0DBD:0400  69 6E 64 6F 77 73 5F 4E-54 00 50 41 54 48 3D 43   indows_NT.PATH=C
Press any key to continue . . .COPY
在重新设定path后,debug命令变得无效。
***共同提高***

TOP

“在重新设定path后,debug命令变得无效。”
debug是外部命令,path变量一改变就找不到文件了

TOP

还是测试说明问题,但也带来了新问题。。。。
代码:
@echo off&setlocal enabledelayedexpansion
for /l %%a in (1,1,100) do set "d=!d!&echo d"
call :lp _str a
call :lp _str b setlocal endlocal
call : ...
batman 发表于 2011-4-23 13:32


有一点大家想过么?

call的话就有堆栈,有堆栈在内存中是否影响变量的赋值耗时?

昨晚我就用call,当然也和设置的变量数过少有关,得出的结论让我迷路。。。

TOP

从大量的测试推断cmd.exe在每次运行时就会用以下命令向内存写入信息从而来设置环境变量:
set "ALLUSERSPROFILE=C:\Documents and Settings\All Users"
set "APPDATA=C:\Documents and Settings\Administrator\Application Data"
set "CommonProgramFiles=C:\Program Files\Common Files"
set "COMPUTERNAME=PC-200901071258"
set "ComSpec=C:\WINDOWS\system32\cmd.exe"
set "FP_NO_HOST_CHECK=NO"
set "HOMEDRIVE=C:"
set "HOMEPATH=\Documents and Settings\Administrator"
set "LOGONSERVER=\\PC-200901071258"
set "NUMBER_OF_PROCESSORS=2"
set "OS=Windows_NT"
set "Path=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\Common Files\Thunder Network\KanKan\Codecs;C:\Program Files\StormII\Codec;C:\Program Files\StormII"
set "PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH"
set "PROCESSOR_ARCHITECTURE=x86"
set "PROCESSOR_IDENTIFIER=x86 Family 15 Model 107 Stepping 2, AuthenticAMD"
set "PROCESSOR_LEVEL=15"
set "PROCESSOR_REVISION=6b02"
set "ProgramFiles=C:\Program Files"
set "PROMPT=$P$G"
set "SESSIONNAME=Console"
set "SystemDrive=C:"
set "SystemRoot=C:\WINDOWS"
set "TEMP=C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp"
set "TMP=C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp"
set "USERDOMAIN=PC-200901071258"
set "USERNAME=Administrator"
set "USERPROFILE=C:\Documents and Settings\Administrator"
set "windir=C:\WINDOWS"COPY
***共同提高***

TOP

95# zm900612
我说的就是这个意思,只是没有说明罢了,呵呵。。。
***共同提高***

TOP

本帖最后由 zm900612 于 2011-4-23 15:05 编辑

99# plp626


我理解错了...而且初中高中的数学,我都没怎么听课,喜欢用自己的方法东拼西凑解题

98# batman


噢,怪不得,我还纳闷老兄怎么可能把这忘了


这话题越来越好玩了,斑竹们继续吵架,我是跑龙套的群众演员,等结果

TOP

本帖最后由 hanyeguxing 于 2011-4-24 06:18 编辑

运行批处理时,命令解释器就复制了系统环境变量进入本地,这些系统变量也就本地化了,而 set 的都是本地,所以用set 也只改变本地环境变量
打个比方,系统变量为其他位置的一个源文件,系统变量本地化就像为他在当前目录创建快捷方式,快捷方式可以随意访问源文件。
而 set 这些本地化的系统变量就相当于修改了快捷方式名称,如何修改都不会改变源文件的名称
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

那清空了本地化操作之后呢?命令解释器是再次复制系统变量进入本地吗?
还有setlocal呢?前后都是本地化操作,为什么endlocal之后能还原上一个setlocal之后的操作呢?

TOP

百度搜索下:变量、环境变量、全局变量、局部变量、静态变量、变量名污染、堆栈……
内容虽然不是很多,可能与批处理也无关,不过一些观点还是值得参考的!~
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

返回列表