惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Hackread – Cybersecurity News, Data Breaches, AI and More
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
V2EX
T
The Blog of Author Tim Ferriss
腾讯CDC
Hugging Face - Blog
Hugging Face - Blog
雷峰网
雷峰网
爱范儿
爱范儿
GbyAI
GbyAI
H
Help Net Security
I
InfoQ
罗磊的独立博客
酷 壳 – CoolShell
酷 壳 – CoolShell
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
Microsoft Security Blog
Microsoft Security Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
N
Netflix TechBlog - Medium
Last Week in AI
Last Week in AI
宝玉的分享
宝玉的分享
云风的 BLOG
云风的 BLOG
Project Zero
Project Zero
P
Privacy & Cybersecurity Law Blog
A
Arctic Wolf
Know Your Adversary
Know Your Adversary
G
Google Developers Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tor Project blog
V
Vulnerabilities – Threatpost
Y
Y Combinator Blog
WordPress大学
WordPress大学
V
Visual Studio Blog
博客园_首页
G
GRAHAM CLULEY
K
Kaspersky official blog
T
Tailwind CSS Blog
T
Threat Research - Cisco Blogs
博客园 - Franky
D
Docker
Security Latest
Security Latest
I
Intezer
有赞技术团队
有赞技术团队
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 【当耐特】
B
Blog RSS Feed
T
The Exploit Database - CXSecurity.com
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻

Keyle's Blog

公司搬家 | Keyle's Blog 听闻的一些故事 | Keyle's Blog 《恶魔轮盘改》项目完整实现详解:架构、流程与双端同步 | Keyle's Blog .net core服务发布经验总结 | Keyle's Blog 凌晨一点的键盘声 | Keyle's Blog 南京游记 | Keyle's Blog 从老活到小 | Keyle's Blog 一代人有一代人的龙虾要养 | Keyle's Blog 在咖啡凉透前救回了博客数据 | Keyle's Blog 时间的参照物 | Keyle's Blog 沈阳游记 | Keyle's Blog 近况二三则 | Keyle's Blog 阳澄湖游记 | Keyle's Blog 欢乐谷游记 | Keyle's Blog 殊途同归的“搜打撤” | Keyle's Blog 中班学习规划 | Keyle's Blog 桐庐三日游 | Keyle's Blog 9月15日起,租房新规正式实施!居住安全、费用明细、租金调整与权益保障全面解读 | Keyle's Blog 游泳与羽毛球 | Keyle's Blog 8月生活碎片 | Keyle's Blog 卡坦岛桌游玩法 | Keyle's Blog 当时间戳“捣乱”时,互联网会发生什么? | Keyle's Blog 该如何去度过一生 | Keyle's Blog 在Lua中循环Require是如何处理的? | Keyle's Blog
补码陷阱 | Keyle's Blog
2025-10-22 · via Keyle's Blog

为什么这个Bug如此狡猾?

直觉背叛:我们直觉上认为 -A 就是 “负的A”,但在位运算中它变成了”A的补码”
测试遗漏:我们测试了正数情况,但对负数的测试不够充分
认知偏差:我们都”知道”补码,但真正用到时却忘了它的存在

你发现下面代码中的问题了吗 ?

1
2
3
4
5
6
7
8
9

bool ShouldSelect(int value, int mask)
{
if (-value & mask == Mathf.Abs(-value))
{
return -value > 0;
}
return false;
}

在C#中,A & B-A & B 的区别主要在于对负数处理的不同。让我通过具体案例来说明:

案例演示

1
2
3
4
5
6
7
8
9
10
int A = 5;    
int B = 3;


int result1 = A & B;
Console.WriteLine($"A & B = {result1}");


int result2 = -A & B;
Console.WriteLine($"-A & B = {result2}");

二进制分析:

1
2
3
4
5
6
7
A = 5:  0000 0101
B = 3: 0000 0011
A & B: 0000 0001 = 1

-A = -5: 1111 1011 (补码表示)
B = 3: 0000 0011
-A & B: 0000 0011 = 3

更多案例

1
2
3
4
5
6
7
8
9
10
11
12

int A2 = 10;
int B2 = 6;

Console.WriteLine($"{A2} & {B2} = {A2 & B2}");
Console.WriteLine($"-{A2} & {B2} = {-A2 & B2}");


int A3 = -3;
int B3 = -5;

Console.WriteLine($"{A3} & {B3} = {A3 & B3}");

背后的意义

1. 补码表示法

  • 在C#中,整数使用二进制补码表示
  • 正数的补码是其本身
  • 负数的补码 = 对应正数的二进制取反 + 1

2. 运算本质

  • A & B:对两个数的实际二进制位进行按位与
  • -A & B:先计算A的补码(得到-A),再与B进行按位与

3. 实际应用场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

[Flags]
enum Permissions
{
Read = 1,
Write = 2,
Execute = 4
}


Permissions userPermissions = Permissions.Read | Permissions.Write;


bool canRead = (userPermissions & Permissions.Read) != 0;


bool wrongCheck = (-(int)userPermissions & (int)Permissions.Read) != 0;

4. 重要注意事项

1
2
3
4

int A = 5, B = 3;
Console.WriteLine($"-A & B = {-A & B}");
Console.WriteLine($"-(A & B) = {-(A & B)}");

总结

  • A & B 是直接的按位与运算,结果可预测
  • -A & B 涉及补码转换,结果取决于负数的二进制表示
  • 在实际编程中,应避免对负数进行无意义的位运算,除非明确理解补码机制
  • 位运算通常用于标志位、掩码操作等场景,应保持操作数的明确性和可读性

本文标题:补码陷阱

文章作者:Keyle

发布时间:2025-10-22

最后更新:2025-10-22

原始链接:https://vrast.cn/posts/55376/

版权声明:©Keyle's Blog. 本站采用署名-非商业性使用-相同方式共享 4.0 国际进行许可