框选一段程序框图,Edit → Create SubVI,两秒钟,LabVIEW 给你一个连接板排得整整齐齐的子 VI,原位置换成一个调用节点。
这个动作太顺手,顺手到很多人做了三五年,都没见过它拒绝执行的样子。
但 CLAD 的每日一题里,光"Create SubVI"这一个动作就占了 9 道题(第 13 讲的 13-10 到 13-18)。出题人不是在考快捷键,是在考框选的那一下,边界在哪里。
这篇把那 9 道题拆开讲,再补上我这些年真正踩过的坑。
01 它到底做了什么
很多人以为 Create SubVI 是"把这段代码复制出去"。不是。
它做三件事,顺序固定:
- 搬走:把选中的节点、常量、连线整体搬到新 VI 的程序框图里;
- 生成连接板:凡是跨越选区边界的线,在边界处被剪断,剪断处生成一个端子,输入端排在左边,输出端排在右边;
- 替换:原位置放一个子 VI 调用节点,用新生成的连接板把线接回去。
关键在第二步。连接板不是"按你的想法排",是按跨界的线自动生成的。 你框得大一点、小一点,跨界的线就变,端子数量和顺序就跟着变------这也是很多人拆完发现"接线全乱了"的真正原因,不是 LabVIEW 乱来,是框选改变了接口。

配图 1
02 它什么时候干脆不干
有三种情况,LabVIEW 会直接拒绝,或者做出来的东西不是你想要的。
第一种:会形成循环调用。
如果选中的这段代码里,间接调用了包含它的这个 VI 自己,拆出去就等于 A 调 B、B 又调 A,成了环。LabVIEW 会拒绝创建,并提示这样会产生循环。
这一条在考试里出现在 13-15:题目给的图里,被选中的部分正好包含了对自己所在 VI 的引用,答案就是"不创建"。
第二种:端子数超过连接板的上限。
连接板最多 28 个端子(这个数字下一篇细讲)。如果框选范围太大,跨界线太多,超了上限就创建不了。13-18 那道题的名字就叫"我到了极限"------它考的不是语法,是让你意识到框选范围本身是有物理上限的。
第三种:框选跨进了结构内部,但边界没对齐。
这类不算"拒绝",它会把结构一起带走,或者只带走一半,结果跟你想的完全不同。13-11 到 13-14、13-16 这几道题,考的全是这个:同样是框选,框在结构内部、框到结构边界、框住整个结构,三种框法出来三个不同的子 VI。

配图 2
03 常量不会变成输入端子
这是 13-10 那个坑,也是实际写代码最容易踩的一个。
图里是一个常量 π 接到一个乘法节点。你框住它,Create SubVI。拆出来的子 VI 里,π 是子 VI 内部的常量,不是一个输入端子。
为什么?因为常量不是"数据源节点",它没有上游。LabVIEW 生成连接板时只给"跨界连线"配端子,常量在选区里,就跟着搬进去了。
这条在考试里是对的,在实际项目里却经常是错的:你本来想让 π 变成可配置的参数,结果它被硬编码进了子 VI,回头要改还得进子 VI 改。想要它变成端子,就不能把常量框进去------把它留在外面,让它接到子 VI 的输入端子上。
同一道题还有个细节值得说:13-10 的正确答案只有一个,选项里那些"LabVIEW 顺手把常量也提成端子"的图,全是干扰项。这类题的套路是:看端子数,就知道哪个是自动生成的。
04 结构边界:三种框法,三个子 VI
13-11 到 13-16 这几道题,图看起来差不多,答案却不一样。差别只在框选范围。
我把它归纳成三句话:
- 框在结构内部:结构留在外面,子 VI 只包含结构里的那部分逻辑。这时候子 VI 的端子对应结构内部的线,藏在结构里的隧道(tunnel)会被保留。
- 框住整个结构:结构跟着搬进子 VI,循环、条件分支都成了子 VI 的内部实现。这时候子 VI 的接口变成结构的输入输出。
- 框到结构边界但没对齐:LabVIEW 会按它的规则补全边界,结果往往既不是你想的 A,也不是你想的 B。
这就是为什么同样的操作,题库能出五道题还不重样------框选不是"选中哪些节点",是"在哪里切断数据流"。
实际项目里的建议只有一条:先想清楚接口,再框。 先问自己"这个子 VI 我要给它几个输入、几个输出",然后倒推框选边界,而不是先框了再看生成什么。

配图 3
05 Feedback Node:同一个操作,不同版本不同结果
13-17 是这份题库里最诚实的一道题。它的答案写的是:取决于 LabVIEW 版本。
题目是框选一段带 Feedback Node 的代码,问 Create SubVI 之后是什么样子。这道题在不同版本上,LabVIEW 对 Feedback Node 的处理确实有差异------早期版本不允许把 Feedback Node 拆进子 VI,后来放开了,但初始化端子的位置和初始值处理又各有不同。
这道题给了一个很重要的提醒:LabVIEW 不是一门"语法固定"的语言,它的行为随版本演进。 你在 2018 上背下来的结论,到 2023 上可能就不成立。
所以我的习惯是:凡是涉及编译器、内存、结构边界的结论,一律在目标版本上实测一遍,别背。题库也一样------它标"版本相关"的地方,是真的版本相关。
06 拆完之后最容易犯的三个错
错误一:连接板端子顺序变了,线接错位。
尤其当输入里有同类型的多个参数(比如三个 double),LabVIEW 按跨界线的位置生成端子,位置一变,顺序就变。调用处的线不会"智能匹配",它按端子序号接,接错了不报错,只是算错。
修法:拆完立刻右键子 VI → VI Properties → 看一眼连接板;或者在调用节点上右键 → 显示连接板,逐个核对。
错误二:错误簇没串上。
拆出去的那段代码如果包含错误处理,错误输入/输出往往会变成两个端子。很多人拆完只顾着连数据线,把错误簇悬空------LabVIEW 不报错,但错误信息从此断流,出了问题查不到源头。
错误三:忘了开可重入。
拆出来的子 VI 如果要在并行的多个地方同时调用(比如两个独立的采集循环),必须开 Reentrant。不开的话,两个调用共享同一份前面板数据空间,轻则数据串味,重则直接报"VI 已在运行"。这一条下一篇会展开。
07 什么该拆,什么别拆
拆子 VI 的收益是三个:复用、可测、可读。
- 同一段逻辑在三个以上地方用到,拆;
- 这段逻辑需要单独喂输入、单独验证,拆;
- 一个程序框图滚三屏还看不完一个功能,拆。
不该拆的也有三个:
- 只调用一次,而且逻辑强内聚。拆出去只是把一屏变两屏,读代码的人要多跳一次。
- 性能敏感的紧循环内部。子 VI 调用有开销,虽然很小,但在微秒级的循环里会累积。这种场合要么别拆,要么拆完开内联(SubVI Inlining,把代码在编译期展开回调用者,下一篇讲)。
- 接口比实现还复杂。如果一个子 VI 有 20 个输入端子,那它不是一个模块,是一段被切碎的代码。
判断标准其实很朴素:拆完之后,调用处的那一行能不能一眼看懂它在干什么。 能,就拆对了;不能,说明接口没设计好,拆之前应该先想接口。

配图 4
写在最后
Create SubVI 这个动作,考的不是操作,是数据流的边界感。
框选的那一下,你实际上是在回答一个问题:这段逻辑,从哪里开始,到哪里结束,它需要什么,它产出什么。 答对了,两秒钟出一个干净的子 VI;答错了,两秒钟出一堆要重接的线。
CLAD 题库里那 9 道题,本质是在训练这个直觉。题库里还有几道题的答案标着"版本相关"或者"原帖未公布"------这不是偷懒,这是提醒你:有些结论只能自己上机验。
下一篇讲连接板:28 个端子怎么排、Required/Recommended/Optional 到底差在哪、动态分配为什么只能有一个输入。
你在拆子 VI 的时候,遇到过最莫名其妙的一次是什么?评论区说说。