【原创】函数中的局部变量是如何实现的
本帖最后由 baitang36 于 2024-8-8 15:29 编辑一般定义函数是这样写的:
(defun tt(v1 v2/ab c) (princ a))
在函数的参数中,斜杠后面的是局部变量,它是如何实现的呢?
反编译一下,发现它调用了一个保留函数_al-bind-alist ,看字面意思是绑定一个列表。
什么是绑定呢?对应的应该有个解绑函数吧?
深入研究,还真的有解绑函数,它叫_unbind 只有一个参数,就是局部变量的个数。
绑定的意思是保存原来的符号值,解绑就是恢复原来的符号值。
这两个函数配合,可以随时绑定和解绑,也就是能自己控制一个符号是全局变量,还是局部变量。
请看试验代码:
(load "c:/00/trf_9.fas")
(tranf "_al-bind-alist")
(tranf "_unbind")
(defun t1 ()
(_al-bind-alist '(a b c))
(setq a "\n这里的a是局部变量")
(princ a)
(_unbind 3)
(princ a)
(princ)
(_al-bind-alist '(a))
(setq a "\n二次绑定试验")
(princ a)
(princ)
(_unbind 1)
(princ a)
(princ)
)
(setq a "\n这里的a是全局变量")
(t1)
函数参数的传递方法和这个类似,是通过24号指令来绑定,在函数结束前用25号指令解绑。
_unbind函数必须和_al-bind-alist配对使用,否则会出现 错误: 出现异常: 0xC0000005 (访问冲突)
这种情况相当于访问并不存在的内存,因此报错。
感谢大佬而分享 在(_al-bind-alist '(a b c))和(_unbind 3)之间,可能还有处理办法,如果用户按了Esc呢? 本帖最后由 baitang36 于 2024-8-8 15:14 编辑
自贡黄明儒 发表于 2024-8-8 15:10
在(_al-bind-alist '(a b c))和(_unbind 3)之间,可能还有处理办法,如果用户按了Esc呢?
如果中途退出函数,可能的后果是没有恢复原来的全局变量,符号的值是局部变量的值。
人为造成这种错误,故意不让它解绑,可能获取到真正的注册码。
本帖最后由 tryhi 于 2024-8-8 15:24 编辑
试了一下_unbind函数也可以在外面用,但前面必须有个_al-bind-alist,也就是说有些需要运行在外面的代码块,可以用这个定义“块”级别的局部变量,不过调用_unbind风险感觉挺大的,一旦出错CAD就致命错误,而且vl-catch-all-apply都无法拦截 tryhi 发表于 2024-8-8 15:18
试了一下_unbind函数也可以在外面用,但前面必须有个_al-bind-alist,也就是说有些需要运行在外面的代码块 ...
如果绑定的个数小于解绑的个数,那一定会崩。 在fearch里面用就挺不错,弥补for这种循环代码块没有局部变量的缺陷 本帖最后由 你有种再说一遍 于 2024-8-8 20:50 编辑
由于AutoLisp语言是global的,不是local的,所以就有把全局变量转为局部变量的骚操作.
其实大家更喜欢的是默认局部变量,然后要全局才声明,而局部变量由编译器自动计算生命周期,而不是自己填入函数后面的括号.这就不得不补充CPU运行原理了,
每个函数运行时都会开辟栈帧,栈帧内变量其实不存在释放(删除资源表记录/置0),而是修改对齐栈指针(ESP或RSP寄存器)来结束函数.
而堆则会进行删除资源等操作.
也就是其实AutoLisp全是跑堆上面的...那么如果要做一个编译器,就可以自行计算生命周期,然后把这个代码到局部函数的头尾了.
例如lispTolisp,然后vlide编译第二份lisp.
不过既然那么复杂,为什么不直接lispToArx/lispToCsharp呢.
真有内涵! 本帖最后由 baitang36 于 2024-8-9 09:44 编辑
你有种再说一遍 发表于 2024-8-8 18:03
由于AutoLisp语言是global的,不是local的,所以就有把全局变量转为局部变量的骚操作.
其实大家更喜欢的是 ...
全局变量在内存中就是个地址,好像找不到exe中的变量名。
页:
[1]