移位操作符深度解析:从二进制原理到实战避坑指南

聊到移位操作符<<和>>,很多人的第一反应是:这玩意儿不就是把二进制位挪一挪吗?真到了写代码,十个有八个会在负数和移位位数上翻车。我搞了几年嵌入式,又做过图形图像处理,移位操作符几乎天天都在碰,可以说它是底层开发里最不起眼又最容易被低估的符号。这篇文章不是教科书式的罗列,而是基于我实际写代码和调错过程中的经验总结,把移位操作符的底层逻辑、不同语言里的坑、实战场景,以及我个人的一些排查心得一次性说清楚。无论你是刚接触位操作的新手,还是已经在用但偶尔被它折磨的老人,这篇内容应该都能给你一些参考。

1. 移位操作符是什么:从二进制视角看 << 和 >>

1.1 移位操作符的数学本质

移位操作符操作的对象是二进制位。左移位x << n的含义,是把整数x的二进制表示整体向左移动n位,最右边空出来的位置补0,最左边被挤出去的位直接丢弃。右移位x >> n则是整体向右移动n位,最右边被挤出去的位丢弃,左边空出来的位置补什么,取决于语言和变量类型。

从数学上看,对一个无符号整数执行x << n,等价于乘以2的n次方。比如3 << 2,二进制11变成1100,也就是12,恰好是3 * 4。同样,对无符号整数执行x >> n,等价于除以2的n次方并向下取整。比如15 >> 2,二进制1111变成11,也就是3,正好是15 / 4的整数部分。这个特性在早期没有硬件乘法器的嵌入式处理器上,是极其重要的优化手段。我在某项目里就曾用移位代替乘法来算像素偏移,速度提升非常明显。

1.2 左移右移的直观理解

如果你以前没接触过二进制,可以把它想象成一个公路上的车队。每个位就是一辆车,<<就是所有车一起往前开,车头前面越界的车掉下悬崖,后面空出来的车位推入一辆无声的“0号车”。>>就是所有车一起往后倒,车尾越界的车被挤掉,前面空出来的车位补“0”或者补“1”,具体补什么就看这辆车的“性格”(有无符号)。

左移的特点非常统一:不管是正数还是负数,也不管是有符号还是无符号,右侧永远补0。所以-1 << 1在大多数语言里结果是-2,因为-1的二进制补码全是1,左移一位后变成...1110,依然解释为-2。

右移就有分歧了。逻辑右移是左侧一律补0,适合无符号数;算术右移是左侧复制原来的符号位,适合有符号数。C/C++ 对无符号数使用逻辑右移,对有符号数则取决于实现,不过绝大多数编译器都采用算术右移。Java 做得更明确:>>是有符号右移,>>>才是无符号右移。这些差异是无数线上事故的根源,后面我会重点展开。

2. 实操细节:不同语言里的移位差异与底层逻辑

2.1 C/C++ 中的移位陷阱

C/C++ 的移位操作符行为,堪称“教科书级”的模糊地带。对于无符号整数,左移和右移都是明确规定的;但对于有符号整数,左移时如果结果超出范围,C++ 标准在 C++20 之前甚至把它归类为未定义行为,右移则在绝大多数场景下是实现定义的。我当年在某图像处理项目里,就遇到过int负数右移后符号扩展导致像素数据越界的问题,排查了一整天才找到根因。

举个具体例子:

int a = -8; int b = a >> 1; printf("%d\n", b);

在主流 x86 编译器和 GCC/Clang 上,输出是-4,因为采用的是算术右移,符号位被扩展。但如果把代码移植到某些特殊平台,理论上是可能出现2147483644这种结果的。所以我的原则是:有符号数右移,除非你完全清楚自己在干什么,否则宁可先用无符号类型做一次强制转换。

另一个坑是移位位数。C 标准要求移位计数必须小于操作数的位宽,比如int是 32 位,a << 32是未定义行为。我见过有人写循环移位,把a << 32挂在 32 位系统上,结果某天优化等级一开,整个程序行为都变了。不要依赖编译器对这种情况的任何“宽容”,它就是禁地。

2.2 Java 和 C# 的逻辑右移

Java 和 C# 把移位分成了>>和>>>两个操作符。>>保留符号位的算术右移,>>>是无脑补0的逻辑右移。这在处理彩色像素时特别有用,因为像素值通常存为int,但你又希望把它当作无符号的 0 到 255 数值来操作。

我有一段经典代码,从 ARGB 颜色值里提取 R、G、B 通道:

int color = 0xA1B2C3D4; int alpha = (color >>> 24) & 0xFF; int red = (color >>> 16) & 0xFF; int green = (color >>> 8) & 0xFF; int blue = color & 0xFF;

这里>>>保证了最高位不会因为符号扩展而污染到第九位以上。如果用>>,遇到带透明度的 PNG 图,最高位是1,右移后左侧补1,再与0xFF相与,值就会完全错乱。这个细节我起码见过三次以上在同事的代码里出现,每次修完都感叹一句:为什么当初不用>>>。

C# 和 Java 类似,也有>>和>>>,只是>>>是从 Java 那继承来的。在写哈希或随机数时,往往需要逻辑右移来消除符号位的影响,这时候>>>比& 0x7FFFFFFF更干净。

2.3 Python 的特殊性

Python 的整数是任意精度的,也就是说它没有“位宽”这个概念。1 << 1000完全合法,结果是一个大整数。这看起来方便,但有时会掩盖你在某些 C 语言式场景下的错误。Python 的右移是算术右移,对有符号负数会保留符号位,所以-8 >> 1结果是-4,和 C 的主流行为一致。

Python 还有一个容易忽略的点:因为整数没有固定位数,所以“溢出”不会告诉你,左移后数可以无限大。在做位运算模拟时,我通常会手动加一个掩码,比如只保留低 32 位:

def rotate_left_32(x, n): n %= 32 mask = 0xFFFFFFFF return ((x << n) | (x >> (32 - n))) & mask

这种写法比直接用 C 语言的移位更安全,因为你在每一步都明确限定了 32 位的边界。

3. 移位操作符的真实应用场景:从位标志到哈希散列

3.1 权限系统与位标志

位标志是移位操作最经典的用途之一。假设一个下载任务有四种属性:可读、可写、可执行、可删除。与其定义四个布尔值,不如用一个int的四个位来分别表示。

#define PERM_READ (1 << 0) #define PERM_WRITE (1 << 1) #define PERM_EXEC (1 << 2) #define PERM_DELETE (1 << 3)
  • 设置权限:perm |= PERM_READ | PERM_WRITE;
  • 清除权限:perm &= ~PERM_WRITE;
  • 判断权限:if (perm & PERM_EXEC) ...

这种方式省内存,而且多个权限的组合本质上就是交集/并集运算,切换非常快。我在某系统里设计过一套日志过滤器,用一个字节存储八个可开关的标志位,通过|和&操作在热路径上高效判断。如果不用位标志,就得用八个布尔变量,不仅缓存不友好,代码还冗余。移位在这里参与的是位掩码的构建,1 << k比你硬编码0x80这类值清晰得多,可读性也更好。

3.2 RGB 颜色与图像处理中的位移

图像处理是移位操作最密集的领域之一。一张 32 位 ARGB 像素,四个通道各占 8 位。任何通道分离和合成,本质上都是一轮移位加掩码操作。我之前写过一个简单的图像滤镜,需要把图像整体向右偏移几个像素,如果按像素逐个计算坐标,每个像素都要做乘法和加法;如果直接对颜色分量做移位,就能把“颜色通道重排”合到同一条流水线里。

典型的通道合代码:

uint32_t argb = (alpha << 24) | (red << 16) | (green << 8) | blue;

这段代码看似简单,但每一处移位都必须确保对应通道不超过 8 位,否则高位的分量会“串门”到相邻通道。我在项目里习惯先做一次掩码再移位,比如(alpha & 0xFF) << 24,避免脏数据污染相邻位。这种习惯在调试从传感器读取的原始帧数据时,能省下大量抓头发的时间。

3.3 哈希散列中的位移混合

在很多哈希算法中,为了让原始输入的细微差异扩散到结果的每一位,会用大量移位、异或和加法做“雪崩效应”。最典型的例子就是经典的散列混合函数,这里面>>与<<的巧妙配合能把数据的相关性打散。

比如某些简易字符串哈希会写成:

hash = (hash << 5) + hash + *str++;

等价于hash = hash * 33 + c,用位移和加法代替乘法,在旧处理器上就是白拿的性能提升。还有一种常见的混淆操作是“异或右移”:

uint32_t h = x; h ^= h >> 16; h *= 0x85ebca6b; h ^= h >> 13;

这里的h >> 16结合异或,能把高位信息传递到低位。如果不理解移位方向,很容易写反,导致哈希结果只集中在一个窄范围里,碰撞率飙升。我在一个分布式缓存的小试验中,就因为把h >> 13写成了h << 13,导致热点 key 的分布严重倾斜,调整后才恢复。移位操作符在散列场景中的方向性,远比你想象的敏感。

4. 上手过程:一个模拟图像处理项目的移位优化记录

为了让你更直观地感受移位操作符在真实项目里怎么用,我讲一个最近做的模拟图像处理 Demo。目标是把一张 24 位真彩色图像转换成灰度图,并做一次水平镜像。第一版按最直观的方式写,结果发现性能不满足要求。后来主要做了三处移位层面的优化。

第一处,灰度公式Y = 0.299R + 0.587G + 0.114B里的浮点乘法,全部替换成整数移位加权。具体做法是放大系数到 256 倍,再用移位和加法完成:

uint8_t gray = (uint8_t)((r * 77 + g * 150 + b * 29) >> 8);

这里77、150、29分别对应0.299*256、0.587*256、0.114*256的近似值。最后的>> 8相当于除以 256,把缩放的权重重现将回来。实测下来比浮点版本快了不少,在低端嵌入式平台上的差距尤其明显。

第二处,水平镜像时要交换像素,我原本是逐字节交换,后来改成用“右移 + 掩码”一次性交换高低字节:

uint8_t swapped = (val >> 4) | (val << 4);

这个操作能把字节内的高低位互换,正好对应了像素通道的镜像需求,比挨个读位再写位干净利落。当然这只是针对半字节镜像的场景,但足以说明移位在处理位级重组时的威力。

第三处,图像对齐。有些压缩格式要求每行字节数是 4 的倍数,读入时按 16 字节对齐会更方便。当我需要把某个值向上对齐到 16 的倍数时,用移位完成除法再乘回去:

uint32_t aligned = (size + 15) & ~15;

这个~15搭配按位与,比先除再乘还要直观,并且完全避免了乘法指令。在这些代码里,<<和>>不是配角,它们就是主体。

这个小项目让我又加深了一个认知:移位操作符优化出来的代码,非但不会变得晦涩,如果命名和注释写清楚,反而比浮点公式更容易看出数据的二进制布局。

5. 那些年踩过的坑:移位常见问题与排查实录

5.1 移位计数超出位数

最常见的低级错误是x << 32写在一个 32 位整数上。很多新手以为结果是0,实际上在 C 和 C++ 里这是未定义行为,编译器可能把32取模成0,也就是不变;但换一个编译器或开启某些优化后,结果就完全不可预期了。我遇到过一次,是在一个循环里把常量32写成了动态变量,某次恰好等于32,程序立刻变得迷之卡顿,后来排查出是因为循环计数越界导致移位位数异常。

处理方式是:要么在移位前判断位数范围,要么使用专门的循环移位封装,要么将变量类型统一提升到 64 位再操作。对于旋转位移,你需要自己处理模数:

uint32_t rotate_left(uint32_t x, int n) { n &= 31; return (x << n) | (x >> ((32 - n) & 31)); }

那个& 31是防止n等于 32 时32 - n变成 0,但客观上会使移位范围有所变形,需要仔细测试。

5.2 优先级问题:a << b + c不是你想的那样

移位操作符的优先级比加法低,比关系运算符高。也就是说a << b + c会被解析为a << (b + c),而不是(a << b) + c。这个坑我印象太深了,当初写一个缓存索引计算:

int index = tag << 8 + offset; // 实际上是 tag << (8 + offset)

结果是索引完全错乱,找了好久才发现是括号问题。从那以后,我规定自己所有包含位运算的表达式一律加括号,哪怕优先级是对的也加。这是成本最低的防错方式。

优先级速查心法:<<和>>的优先级介于算术运算符和关系运算符之间,所以凡是和加减乘除、比较逻辑混用的地方,全都要显式括号。

5.3 负数左移/右移的未定义行为

C/C++ 里对负数左移,只要结果没有溢出,是不是安全的?这是个微妙的边界。C++20 之前,左移负数在某些编译器下是未定义行为。虽然主流编译器都给出“符合直觉”的结果,但严格讲你不应该依赖。我的建议是:如果真的需要负数移位,就用无符号类型做中介。

int x = -16; int y = (int)((unsigned)x >> 2);

这样至少把行为限制在“明确无符号右移”,然后由你决定如何把结果解释成有符号。类似地,不要在同一个表达式中混用有符号位运算和无符号位运算,类型提升规则会把你折磨疯。

5.4 有符号与无符号混淆

混合蘸酱式编码最容易出错。有符号整数右移是算术右移,补符号位;无符号整数右移是逻辑右移,补零。你把一个uint32_t强制转换成int后右移,移出来的高位是1还是0,直接取决于转换后的语义。某次我在排查网络字节序转换时,发现高字节丢失,就是因为把unsigned char提升成了int,然后对int做右移,字符的最高位被符号扩展到了整数的前 24 位。

正确写法通常是这样:

uint8_t high = (uint8_t)(value >> 8); uint8_t low = (uint8_t)value;

在移位前先做好类型控制,结果的类型明确,再移位,最后截断。不要在移位的同一行里既做类型转换又做逻辑判断,那种代码读起来太累了。

6. 几个我常用的调试技巧与心得

6.1 打印二进制辅助排查

排查移位问题时,我最喜欢写一个打印二进制的小函数。

void print_binary(uint32_t v, int bits) { for (int i = bits - 1; i >= 0; i--) { putchar((v & (1u << i)) ? '1' : '0'); } putchar('\n'); }

在怀疑移位方向搞错时,把计算前后的值都用二进制打出来,一眼就能看出位去了哪里。别相信自己的脑子,位运算错位一个 bit,肉眼在十进制里根本看不出来。

6.2 用常量掩码代替魔法数字

经常有人写x & 0xFF非要写成x & 255,其实两者等价。但更推荐用0xFF这种“掩码语言”,因为它能直观告诉你操作的是低 8 位。同理,1 << 7比128更能表达“最高位”的含义。代码是给人看的,重点在于把自己的意图通过位运算清晰地表达出来。

6.3 善用编译器的常量折叠与优化

现代编译器对常数移位有很强的优化能力。比如x << 3会被编译成lea指令或者直接乘以 8,很多时候并不比乘法慢多少。所以不要为了炫技而过度使用移位。只有当代码语义本身是“位的搬运”时,移位才比乘法更合适。如果只是单纯乘以 2,直接写x * 2,编译器也会优化成移位。过度使用反而会让同事骂你。

7. 关于移位操作符,我的最终建议

如果你刚开始玩位运算,我建议先从“无符号整数左移右移”开始,把1 << k当成生成位掩码的基本工具,把x & mask当成保留某些位的过滤器。每写一行移位代码,都问自己三个问题:当前变量是有符号还是无符号?右移补的是符号位还是零?移位位数会不会超过类型位宽?

这三问,能过滤掉八成以上的低级错误。剩下的两成,基本都藏在“优先级混乱”和“类型提升”里。把这两点刻进肌肉记忆之后,你再看别人写的位运算代码,会轻松很多。

我个人的体会是:移位操作符是少数的、能同时提升代码性能和编码效率的底层语法。它表面上简单,但每一个细节背后都牵扯着二进制补码、类型系统、编译器优化这些硬知识。如果你想深入底层开发,值得花一个下午把这些边边角角全部捋清楚。这篇文章写下的,就是我踩过那些坑后留下的路线图。希望对你有用。

相关新闻

使用 Rust 接入 Azure Service Bus:agentic-awesome-skills 官方技能中的队列、主题与可靠消息收发实战指南

使用 Rust 接入 Azure Service Bus:agentic-awesome-skills 官方技能中的队列、主题与可靠消息收发实战指南

AI 技能AI 插件人工智能 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600 agentic skills. Includes CLI, local MCP, c…

2026/10/21 3:49:32 阅读更多 →
WPF实时相机显示:DispatcherTimer与Halcon集成实战

WPF实时相机显示:DispatcherTimer与Halcon集成实战

1. 为什么要在WPF里用DispatcherTimer做实时相机显示做过机器视觉上位机的人都有一个共识&#xff1a;相机取图这件事&#xff0c;最怕的不是算法跑不动&#xff0c;而是界面卡死。你辛辛苦苦把Halcon的算子调通了&#xff0c;图像处理结果也对了&#xff0c;结果一开实时预览&…

2026/10/21 3:49:31 阅读更多 →
BrewUI:Homebrew 官方图形界面完整指南

BrewUI:Homebrew 官方图形界面完整指南

BrewUI&#xff1a;Homebrew 官方图形界面完整指南 【免费下载链接】BrewUI &#x1f4fa; Homebrews official macOS GUI 项目地址: https://gitcode.com/GitHub_Trending/br/BrewUI Mac 上装软件长期有两条路&#xff1a;把 .dmg 拖进 Applications&#xff0c;或在终…

2026/10/21 3:49:31 阅读更多 →

最新新闻

Buck-Boost变换器仿真设计:从开环计算到闭环补偿

Buck-Boost变换器仿真设计:从开环计算到闭环补偿

最近在做某车载电源项目时&#xff0c;需要把一个波动范围很宽的电池电压&#xff08;9V到16V&#xff09;稳定成5V输出&#xff0c;给传感器电路供电。输入可能比输出高&#xff0c;也可能比输出低&#xff0c;普通的Buck或Boost拓扑都搞不定&#xff0c;只能上Buck-Boost。而…

2026/10/21 7:19:55 阅读更多 →
卫星图像降雨预测实战:从数据对齐到模型部署的完整技术路线

卫星图像降雨预测实战:从数据对齐到模型部署的完整技术路线

卫星图像预测降雨&#xff0c;听起来像是一个标准计算机视觉任务&#xff1a;数据是云图&#xff0c;标签是雨量&#xff0c;训练一个分割模型就完事。我第一次接触这类需求时也是这么想的&#xff0c;真到动手才发现&#xff0c;模型反而是整个链条里最不费心思的部分&#xf…

2026/10/21 7:19:55 阅读更多 →
AI Agent编排层故障排查:上下文窗口、工具调用与稳定性的工程实践

AI Agent编排层故障排查:上下文窗口、工具调用与稳定性的工程实践

很长一段时间里&#xff0c;我都在围绕 AI Agent 的编排层做工作&#xff0c;也就是圈子里常说的 Agent Harness Engineering。这个环节介于模型能力和业务场景之间&#xff0c;干的是工具注册、上下文管理、状态流转、调用编排这些不怎么光鲜、但是决定系统能不能真正跑起来的…

2026/10/21 7:19:55 阅读更多 →
基于PyTorch的时空预测模型复现:图卷积与时间卷积工程实践

基于PyTorch的时空预测模型复现:图卷积与时间卷积工程实践

简介&#xff1a;这是一份面向时空预测模型研究与PyTorch进阶学习者的PyTorch复现代码包。针对交通流量、气象等序列预测场景&#xff0c;资源将多个论文模型拆解为内聚的小Module再组装&#xff0c;便于读者对照公式与图示理解结构&#xff0c;并适配(batch, sequence, channe…

2026/10/21 7:19:55 阅读更多 →
AI威胁检测实战指南:从数据治理到模型落地的全链路解析

AI威胁检测实战指南:从数据治理到模型落地的全链路解析

今年一直在折腾一套东西&#xff1a;把AI和大数据技术揉进安全检测里&#xff0c;做智能威胁检测。说白了&#xff0c;就是让机器自己去流量、日志里找坏人&#xff0c;别总靠人肉盯。这个方向最近特别火&#xff0c;但真正落地过的人都知道&#xff0c;里面坑多水深&#xff0…

2026/10/21 7:19:55 阅读更多 →
寒区块石路基水热力耦合与冻胀变形的COMSOL模拟要诀

寒区块石路基水热力耦合与冻胀变形的COMSOL模拟要诀

一提到寒区路基&#xff0c;干这行的人第一反应通常都是那六个字——冻胀、融沉、翻浆。我前两年接了一个某寒区道路工程的数值评估任务&#xff0c;核心就是把一段块石路基的水热力耦合行为在COMSOL里算清楚&#xff0c;最后落到冻胀变形预测上。这类项目看着是纯仿真&#xf…

2026/10/21 7:18:55 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事&#xff1a;AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里&#xff0c;按宣传口径&#xff0c;本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”&#xff0c;而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起&#xff1a;用户到底在追求什么“封号重开”这四个字&#xff0c;放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流&#xff0c;背后是大量的时间和精力成本。正常情况下&#xff0c;没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”&#xff0c;而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时&#xff0c;就意识到&#xff1a;单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/21 4:27:17 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/20 9:50:45 阅读更多 →