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

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
L
LangChain Blog
Vercel News
Vercel News
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
T
Threatpost
Scott Helme
Scott Helme
T
Tailwind CSS Blog
Latest news
Latest news
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
The Register - Security
The Register - Security
罗磊的独立博客
P
Proofpoint News Feed
腾讯CDC
S
Schneier on Security
雷峰网
雷峰网
A
About on SuperTechFans
T
Tenable Blog
F
Full Disclosure
Cyberwarzone
Cyberwarzone
博客园_首页
有赞技术团队
有赞技术团队
K
Kaspersky official 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日起,租房新规正式实施!居住安全、费用明细、租金调整与权益保障全面解读 游泳与羽毛球 8月生活碎片 卡坦岛桌游玩法
补码陷阱 | Keyle's Blog
2025-10-22 · via

为什么这个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 国际进行许可