news 2026/9/26 3:16:55

Catch2 命令行完全指南:TEN-framework 依赖中 clingo 测试框架的过滤、报告与基准选项详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Catch2 命令行完全指南:TEN-framework 依赖中 clingo 测试框架的过滤、报告与基准选项详解
  • 人工智能
  • AI Agent
  • 多模态
  • 语音
  • AI 应用

【免费下载链接】ten-framework

Open-source framework for conversational voice AI agents

项目地址:https://gitcode.com/TEN-framework/ten-framework
点击查看免费下载

<输出文章>

Catch2 命令行完全指南:过滤、报告、分片与基准选项实战详解

本文以当前仓库中随附的 Catch2(v3 系)官方文档command-line.md为骨架,系统讲解 Catch2 测试二进制支持的全部命令行选项——从测试过滤、Reporter 选择、输出控制,到执行顺序、随机种子、测试分片与基准统计。同时结合本仓库内 Catch2 源码(catch_commandline.cpp)与 clingo 项目中的实际用法,给出可复制、可运行的真实示例。读完本文,你将能够熟练编写 Catch2 命令行,精准筛选测试、定制报告输出、控制失败中止策略、实现跨进程测试分片,并深入理解底层参数解析机制。


一、背景:Catch2 在仓库中的位置

Catch2 是一个 C++ 测试框架,以"只需一个头文件即可集成"和"BDD 风格、丰富的断言宏"著称。在本仓库中,Catch2 以第三方依赖的形式被 clingo(Answer Set Programming 求解器)及其子项目 clasp、libpotassco 使用:

  • 测试入口通过#define CATCH_CONFIG_MAIN让 Catch2 自动生成main(),例如clasp/libpotassco/tests/main.cpp中的注释就明确写道:"This tells Catch to provide a main() - only do this in one cpp file";
  • 命令行参数的实际解析逻辑位于catch_commandline.cpp,本文每讲解一个选项,都会指出其在源码中的对应注册位置。

因此,本文所有命令示例中的./tests可以替换为任何链接了 Catch2 的测试可执行文件(如 clingo 的测试二进制)。


二、指定要运行的测试(Test Spec 过滤)

Catch2 完全不传命令行参数也能正常工作:此时会运行所有非隐藏测试用例。一个测试用例被视为隐藏,当且仅当它带有[!benchmark]标签,或带有以点开头的标签(如[.]、[.foo])。

测试规格(test spec)由三种基本形式组合而成:

基本形式示例匹配规则
完整测试名"Test 1"仅匹配名为 "Test 1" 的用例
通配测试名"*Test"、"Test*"、"*Test*"匹配以、开头、或中间包含 "Test" 的用例;通配符只能出现在开头或结尾
标签名[some-tag]匹配带[some-tag]标签的所有用例

三种基本规格可以组合成更复杂的过滤条件:

  • 串联(AND):[some-tag][other-tag]匹配同时具有两个标签的用例,只带其中一个标签的不通过;
  • 逗号连接(OR):[some-tag],[other-tag]匹配任一标签的用例,同时带两个标签的当然也通过。注意逗号的优先级高于简单串联,[a][b],[c]等价于"同时带 a 和 b"或"带 c";
  • 取反(NOT):在规格前加~,如~[some-tag]拒绝所有带该标签的用例。取反只作用于紧随其后的那个基本规格,因此~[foo][bar]只否定[foo],不否定[bar]。

Catch2 的筛选决策顺序是:先检查用例是否命中任何否定过滤,命中即拒绝;之后若不存在肯定过滤,则运行所有剩余非隐藏用例;若存在肯定过滤,则只运行命中的用例。

特殊字符可以用反斜杠转义:名为"Do A, then B"的测试可用规格"Do A\, then B"匹配,反斜杠本身也可以转义自身(\\)。

过滤示例对照表

假设有以下测试用例:

TEST_CASE("Test 1") {} TEST_CASE("Test 2", "[.foo]") {} TEST_CASE("Test 3", "[.bar]") {} TEST_CASE("Test 4", "[.][foo][bar]") {}

各过滤器的结果如下(./tests为测试可执行文件名):

./tests # 只选中第一个测试,其余都是隐藏的 ./tests "Test 1" # 只选中第一个测试,其他名称不匹配 ./tests ~"Test 1" # 一个都不选:Test 1 被拒绝,其余是隐藏的 ./tests "Test *" # 选中全部测试 ./tests [bar] # 选中测试 3 和 4 ./tests ~[foo] # 选中测试 1(唯一没有 [foo] 标签的非隐藏测试) ./tests [foo][bar] # 选中测试 4 ./tests [foo],[bar] # 选中测试 2、3、4 ./tests ~[foo][bar] # 选中测试 3(2 和 4 因带 [foo] 被拒绝) ./tests ~"Test 2"[foo] # 选中测试 4(测试 2 被显式拒绝) ./tests [foo][bar],"Test 1" # 选中测试 1 和 4 ./tests "Test 1*" # 选中测试 1(通配符可匹配零个字符)

实战提醒:命令行中的裸星号(*)可能被 shell 展开。务必确保星号传给 Catch2 而不是被 shell 解释,建议给规格加引号,如./tests "*Test*"。

在源码层面,测试规格被当作位置参数(Arg( config.testsOrTags, "test name|pattern|tags" ))注册在catch_commandline.cpp,可以出现多次并参与上述组合逻辑。


三、选择 Reporter(输出格式)

-r, --reporter <reporter[::key=value]*>

Reporter 决定了 Catch2 输出(断言结果、测试与基准的统计等)的格式与写入方式。默认 reporter 名为console,提供相对详细且对人类友好的输出。

Reporter 支持独立配置:在 reporter 规格后追加::key=value即可,可多次追加,例如:

--reporter xml::out=someFile.xml --reporter custom::colour-mode=ansi::Xoption=2

配置键有两类:

  • 以X前缀开头的键,Catch2 不做解析,原样下传给 reporter(reporter 仍可能校验其合法性并抛错);
  • Catch2 硬编码的内置键,目前只有两个:out(即-o)和colour-mode。

reporter 的::key=value参数传递支持是 Catch2 3.0.1 引入的。

内置 reporter 有多个,可用--list-reporters查看它们的说明;需要自定义格式时,可参考 reporter 文档的"编写你自己的 reporter"章节。

该选项可以多次传递以同时使用多个不同的 reporter(Catch2 3.0.1 起支持)。注意:同时最多只有一个 reporter 可以不指定输出文件,未指定输出文件的 reporter 会使用默认输出目标(由-o, --out决定)。另外,当前 reporter 规格中无法转义::,因此 reporter 名称及配置键值中不能包含::。

从源码看,reporter 解析由setReporterlambda 完成(catch_commandline.cpp):先调用parseReporterSpec解析规格,再从注册表getRegistryHub().getReporterRegistry().getFactories()中查找工厂;找不到会报Unrecognized reporter并提示用--list-reporters查看;同时会检查"未指定输出文件的 reporter 最多一个"这一约束。


四、失败时进入调试器

-b, --break

在大多数调试器下,Catch2 能自动在测试失败处中断,让开发者直接查看失败瞬间的测试状态。源码中对应config.shouldDebugBreak("-b"["--break"],见catch_commandline.cpp)。


五、显示成功测试的结果

-s, --success

默认只报告失败测试。当你怀疑"刚加的测试第一次就跑通了"时,可以用本选项查看全部输出。注意每个 reporter 对此选项的处理可能不同——例如 Junit reporter 本来就会记录所有结果。


六、达到一定失败数后中止

-a, --abort -x, --abortx [<failure threshold>]

Catch2 的断言行为:REQUIRE失败会中止当前测试用例,但后续用例仍会继续;CHECK失败甚至不会中止当前用例。这有时会导致失败消息刷屏,而你只想看到前几个。

  • 单独使用-a或--abort:在任意断言第一次失败时中止整个测试运行;
  • 使用-x或--abortx并跟一个数字:在该数量的断言失败后中止。

源码实现中-a把config.abortAfter设为 1,-x则把参数值赋给abortAfter(见catch_commandline.cpp)。


七、列出可用的测试、标签与 Reporter

--list-tests --list-tags --list-reporters --list-listeners
  • --list-tests:列出所有匹配指定测试规格的已注册测试。通常还附带标签,根据 verbosity 和 reporter 设计还可能包含源码位置等信息;
  • --list-tags:列出所有标签,通常附带匹配的测试用例数量;
  • --list-reporters:列出所有可用 reporter 及其描述;
  • --list-listeners:列出所有已注册的 listener 及其描述(Catch2 3.0.1 新增)。

--list*系列选项自 Catch2 3.0.1 起可通过 reporter 定制。

--verbosity会改变默认--list*输出的详细程度:

选项normal(默认)quiethigh
--list-tests测试名和标签仅测试名同 normal,另加源码行号
--list-tags标签和数量同 normal同 normal
--list-reportersReporter 名和描述仅 Reporter 名同 normal
--list-listenersListener 名和描述同 normal同 normal

八、输出到文件

-o, --out <filename>

将全部输出写到文件而非 stdout。可以用-作为文件名显式输出到 stdout(例如配合多 reporter 时使用;-支持在 Catch2 3.0.1 引入)。

以%(百分号)开头的文件名被 Catch2 保留用于元流(meta stream),例如%debug作为文件名会打开写入平台特定调试/日志机制的流。Catch2 目前识别 3 个元流:

元流写入目标
%debug平台特定的调试/日志输出
%stdoutstdout
%stderrstderr

%stdout与%stderr在 Catch2 3.0.1 引入。


九、命名一次测试运行

-n, --name <name for test run>

为本次测试运行指定名称,reporter 会把它用作整体标题。这在输出到文件、需要区分不同运行(不同 Catch 可执行文件,或同一可执行文件的不同参数组合)时很有用。未指定时默认使用可执行文件名。


十、跳过预期抛异常的断言

-e, --nothrow

跳过所有测试"是否抛出异常"的断言,例如REQUIRE_THROWS。在某些调试环境中,异常抛出(即使是已捕获的)会触发断点,此选项可以避免干扰。此外,如果代码在非断言处也会抛出异常(如被测代码内部抛了又捕获),可以用[!throws]标签标记整个测试用例,在-e模式下跳过整个用例。注意:此选项会改变后续测试的行为,使用需谨慎。


十一、让空白字符可见

-i, --invisibles

当字符串比较因空白差异(尤其是首尾空白)失败时,肉眼很难看出问题。此选项会在打印时将制表符和换行符分别转换为\t和\n显示。


十二、警告(Warnings)

-w, --warn <warning name>

可以把 Catch2 的警告理解为 C++ 编译器-Werror(/WX)的测试版:把一些可疑情况(如没有断言的 SECTION)从"提醒"升级为错误。因为这类情况可能是刻意为之,警告默认不开启,由用户显式启用,且可同时启用多个。目前实现的两个警告:

NoAssertions // 若测试用例/叶子 SECTION 中没有任何断言(如 REQUIRE),则判失败 UnmatchedTestSpec // 若某个 CLI 测试规格没有匹配到任何测试,则本次运行判失败

UnmatchedTestSpec在 Catch2 3.0.1 引入。NoAssertions对排查"空测试"非常有效,可在 CI 中配合-w NoAssertions防止无效测试悄悄通过。


十三、报告耗时(Timings)

-d, --durations <yes/no> -D, --min-duration <value>
  • -d yes:报告每个测试用例的耗时,单位为秒、精确到毫秒,无论通过还是失败都会报告。注意某些 reporter(如 Junit)无论是否设置本选项都会报告耗时;
  • -D, --min-duration <value>(Catch2 2.13.0 引入):只报告耗时超过<value>秒的用例。该选项会被-d yes和-d no覆盖——即设置后要么全部报告、要么全部不报告。

源码中-d直接映射为ShowDurations::Always/Never,-D写入config.minDuration(见catch_commandline.cpp)。


十四、从文件加载要运行的测试

-f, --input-file <filename>

指定一个包含测试用例名列表的文件,每行一个,空行会被跳过。生成该文件初始内容的便捷方式:先用--list-tests配合--verbosity quiet输出纯测试名,再用测试规格过滤出目标子集。


十五、指定测试用例的执行顺序

--order <decl|lex|rand>

三种顺序:

  • decl(默认):声明顺序。同一翻译单元内的测试按声明顺序排序,不同翻译单元之间按实现(链接)相关的顺序;
  • lex:字典序,按测试名排序,忽略标签;
  • rand:随机顺序。顺序取决于 Catch2 的随机种子(见下节--rng-seed),且具备子集不变性(subset invariant):只要随机种子固定,只运行部分测试(如按标签过滤)不会改变它们的相对顺序。

子集稳定性自 Catch2 v2.12.0 引入。自此版本起,官方承诺:给定相同随机种子,只要针对相同版本的 Catch2 编译,不同平台上测试顺序一致;Catch2 不同版本之间允许改变相对顺序,但这不常发生。


十六、指定随机数生成器的种子

--rng-seed <'time'|'random-device'|number>

设置 Catch2 使用的随机数生成器种子,例如用户要求随机顺序(--order rand)时的洗牌种子。三种取值:

  • time:通过std::time(nullptr)生成种子。随机性很弱,若两次运行时间接近可能得到相同种子;
  • random-device:使用std::random_device。只要实现提供了可用的std::random_device就应优先于time;
  • 数字:直接指定整数种子,可复现特定随机顺序,是 CI 上复现随机失败的首选方式(把失败运行的种子固定下来再重跑)。

默认值:Catch2 默认使用std::random_device。


十七、按 libIdentify 标准标识框架与版本

--libidentify

按 LibIdentify 标准 输出框架名称与版本信息,便于外部工具识别运行的是哪个测试框架、什么版本。对应源码注册为config.libIdentify(见catch_commandline.cpp)。


十八、等待按键后再继续

--wait-for-keypress <never|start|exit|both>

让可执行文件打印一条消息并等待回车键:start表示运行任何测试之前等待,exit表示运行完所有测试之后等待,both表示两者都要,never不等待。适合在交互式终端里观察输出流。源码中由setWaitForKeypress解析为WaitForKeypress枚举的四种取值(见catch_commandline.cpp)。


十九、基准测试(Benchmark)相关选项

Catch2 内置基准测试支持,以下选项用于控制采样与统计分析。

跳过所有基准

--skip-benchmarks

跳过运行所有基准(Catch2 3.0.1 引入)。注意:这里的"基准"指BENCHMARK和BENCHMARK_ADVANCED宏中的代码块,不包括带[!benchmark]标签的测试用例。

采样数量

--benchmark-samples <# of samples>

运行基准时会收集若干"样本(samples)",这是后续统计分析的基础数据。每个样本内部会运行依赖时钟分辨率的若干次迭代(与样本数无关)。默认 100(Catch2 2.9.0 引入)。

自助法(bootstrapping)重采样数量

--benchmark-resamples <# of resamples>

测量完成后,会对样本执行统计自助法。重采样数量可配置,默认 100000(Catch2 2.9.0 引入)。通过自助法可以给出均值与标准差的估计,并附带上下界和置信区间(置信区间可配置,默认 95%)。

置信区间

--benchmark-confidence-interval <confidence-interval>

用于自助法统计、计算均值与标准差上下界的置信区间,取值必须介于 0 和 1 之间,默认 0.95(Catch2 2.9.0 引入)。

关闭统计分析

--benchmark-no-analysis

指定后不做任何自助法或统计分析,只测量用户代码并报告样本的朴素均值(Catch2 2.9.0 引入)。适合只想快速看吞吐、不关心置信区间的场景。

预热时间

--benchmark-warmup-time <毫秒>

配置每个测试的预热时间,单位毫秒,默认 100(Catch2 2.11.2 引入)。

以上选项在源码中集中注册于catch_commandline.cpp,其帮助文本直接标明了默认值:samples 默认 100、resamples 默认 100000、confidence interval 默认 0.95、warmup time 默认 100ms。


二十、显示帮助

-h, -?, --help

将全部命令行参数打印到 stdout。


二十一、指定要运行的 SECTION

-c, --section <section name>

把执行范围限制到测试用例内的特定 SECTION,可多次使用;后续每次指定都会深入一层嵌套。例如:

TEST_CASE( "Test" ) { SECTION( "sa" ) { SECTION( "sb" ) { /*...*/ } SECTION( "sc" ) { /*...*/ } } SECTION( "sd" ) { /*...*/ } }
  • 只运行sb:./MyExe Test -c sa -c sb
  • 只运行sd:./MyExe Test -c sd
  • 运行sa全部(含sb和sc):./MyExe Test -c sa

需要注意的局限:

  • SECTION 之外的代码仍会执行——例如TEST_CASE中第一个 SECTION 之前的任何 setup 代码不会被跳过;
  • 当前 SECTION 名不支持通配符;
  • 如果未先用测试名收窄范围,则所有测试用例都会执行(但各自只跑匹配的 SECTION)。

二十二、文件名作为标签

-#, --filenames-as-tags

给所有测试用例额外加一个标签:#加上测试用例定义所在的非限定文件名,并去掉最后一个扩展名。例如tests\SelfTest\UsageTests\BDD.tests.cpp中的测试会被加上[#BDD.tests]标签。由此可以按源文件批量筛选测试,例如:

./tests [#BDD.tests]

二十三、覆盖输出颜色

--colour-mode <ansi|win32|none|default>

Catch2 支持两种终端着色方式,默认会自动猜测用哪种实现、以及是否该用(例如写入文件时会避免输出颜色码)。--colour-mode允许显式指定:

  • ansi:总是使用 ANSI 颜色码,即使写入文件也如此;
  • win32:使用基于 Win32 终端 API 的颜色实现;
  • none:完全禁用颜色;
  • default:交给 Catch2 自行判断,也是默认设置。

--colour-mode在 Catch2 3.0.1 中取代了旧的--colour选项。源码中由setDefaultColourMode解析并写入config.defaultColourMode(见catch_commandline.cpp)。


二十四、测试分片(Test Sharding)

--shard-count <#number of shards>, --shard-index <#shard index to run>

当指定--shard-count <N>时,待执行的测试会被均匀分成 N 组,组编号从 0 开始;--shard-index <i>指定本次运行第 i 组。默认shard-count为 1,默认shard-index为 0。

  • 约束:shard-index必须小于shard-count,因为它被当作要运行的分片索引;
  • 用途:把测试执行拆分到多个进程并行,这与 Bazel 的测试分片模式类似。

分片功能在 Catch2 3.0.1 引入。源码中对--shard-count做了严格校验:解析失败或为 0 都会报错("Shard count must be positive"),见catch_commandline.cpp。

CI 中的典型用法(例如 4 个并行 worker):

# worker 0 ./tests --shard-count 4 --shard-index 0 # worker 1 ./tests --shard-count 4 --shard-index 1 # worker 2 ./tests --shard-count 4 --shard-index 2 # worker 3 ./tests --shard-count 4 --shard-index 3

二十五、允许在没有任何测试时以成功退出

--allow-running-no-tests

默认情况下,如果没有运行任何测试(例如二进制未编译进测试、测试规格未匹配到任何用例,或所有测试在运行时被跳过),Catch2 测试二进制会返回非 0 退出码。本选项(Catch2 3.0.1 引入)覆盖此行为,使"无测试"的运行也返回 0。对应源码为config.allowZeroTests(见catch_commandline.cpp)。在 CI 流水线中,若想容忍"暂时没有匹配测试"的阶段,可考虑使用此选项,但更推荐配合-w UnmatchedTestSpec把"规格没匹配"显式暴露出来。


二十六、输出详细程度(Verbosity)

-v, --verbosity <quiet|normal|high>

改变 reporter 输出的细节量。但请把改变 verbosity 视为一种建议:并非所有 reporter 都支持所有级别(例如有些 reporter 的格式无法有意义地变化),此时该设置会被忽略。默认值为normal。

源码中setVerbosity把quiet、normal、high映射为Verbosity::Quiet/Normal/High,无法识别的值会直接报错(见catch_commandline.cpp)。


二十七、选项速查表

选项短选项作用默认值/说明
<test-spec> ...—按名称/通配/标签过滤测试不传则运行全部非隐藏用例
--help-h, -?打印帮助—
--success-s也显示成功测试结果默认只显示失败
--break-b失败时进入调试器—
--nothrow-e跳过异常断言配合[!throws]标签
--invisibles-i显示制表符/换行为\t/\n—
--out <file>-o输出到文件支持-、%debug、%stdout、%stderr
--reporter <spec>-r选择 reporter默认 console;可多 reporter
--name <name>-n命名本次运行默认可执行文件名
--abort-a首次失败即中止—
--abortx <n>-x失败 n 次后中止—
--warn <name>-w启用警告NoAssertions、UnmatchedTestSpec
--durations <yes/no>-d报告每个用例耗时—
--min-duration <sec>-D只报告超过阈值的耗时2.13.0 引入
--input-file <file>-f从文件加载测试名列表每行一个
--order <decl/lex/rand>—执行顺序默认 decl
--rng-seed <seed>—随机种子默认random-device
--libidentify—按 libIdentify 标准输出标识—
--wait-for-keypress <mode>—等待按键never/start/exit/both
--skip-benchmarks—跳过全部基准3.0.1 引入
--benchmark-samples <n>—采样数量默认 100
--benchmark-resamples <n>—自助法重采样数默认 100000
--benchmark-confidence-interval <v>—置信区间0~1,默认 0.95
--benchmark-no-analysis—关闭统计分析只报朴素均值
--benchmark-warmup-time <ms>—预热时间默认 100ms
--section <name>-c只运行指定 SECTION可多次、逐层深入
--filenames-as-tags-#文件名作为标签如[#BDD.tests]
--colour-mode <mode>—覆盖着色方式ansi/win32/none/default
--shard-count <n>—分片总数默认 1
--shard-index <i>—运行第 i 片默认 0;必须小于 shard-count
--allow-running-no-tests—无测试也返回 03.0.1 引入
--verbosity <level>-v输出详细程度quiet/normal/high,默认 normal

二十八、在仓库中继续深入

  • 本文主体文档:third_party/clingo-sys/clingo/third_party/catch/docs/command-line.md
  • 命令行解析源码:third_party/clingo-sys/clingo/third_party/catch/src/catch2/internal/catch_commandline.cpp
  • 自定义 reporter 指南:third_party/clingo-sys/clingo/third_party/catch/docs/reporters.md
  • 运行时跳过/通过/失败机制:third_party/clingo-sys/clingo/third_party/catch/docs/skipping-passing-failing.md
  • clingo 项目中 Catch2 的实际测试入口:third_party/clingo-sys/clingo/clasp/libpotassco/tests/main.cpp
  • 分片相关 CMake 辅助脚本:third_party/clingo-sys/clingo/third_party/catch/extras/CatchShardTests.cmake

结合本仓库内的源码阅读上述实现,你会发现:所有选项最终都汇聚到catch_commandline.cpp中基于 Clara 库构建的cli表达式(ExeName | Help | Opt(...) | Arg(...)),通过parseUInt、toLower等工具做严格的输入校验。掌握这一入口文件,就等于掌握了 Catch2 命令行行为的全部底层逻辑。

  • 人工智能
  • AI Agent
  • 多模态
  • 语音
  • AI 应用

【免费下载链接】ten-framework

Open-source framework for conversational voice AI agents

项目地址:https://gitcode.com/TEN-framework/ten-framework
点击查看免费下载

相关推荐

上一篇:LifeOS DA_IDENTITY.md 深度解析:数字助理身份体系的配置、生成与运行时加载
下一篇:MediaGo 前端 localStorage 实战指南:版本化键名与最小化存储

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 3:15:33

Cursor 配 TaoToken:AI 编程新纪元的 settings.json 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/26 3:15:33

Cursor 调试 C++ 总失败?用 TaoToken 统一 Key 打通 vsdbg 配置链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/26 3:15:18

I2C总线从开漏到多主仲裁:嵌入式工程师踩坑与实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/26 3:15:14

C盘总是爆满?手把手教你将虚拟内存从C盘迁移到D盘

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华