大家工作中对位操作的使用是什么态度

2019-07-30 18:31:50 +08:00
 lihongjie0209

有些时候确实挺方便的, 但是不那么"直观"(对于团队中的其他人)

大家的看法是什么

7436 次点击
所在节点    程序员
76 条回复
iwtbauh
2019-07-30 23:40:45 +08:00
@mason961125 #16

为什么不用位域呢
mason961125
2019-07-30 23:46:34 +08:00
@iwtbauh #41 读 I/O 电平存一个字节为啥要用位域?
iwtbauh
2019-07-30 23:50:51 +08:00
@jaskle #27

不对。对齐的目的是防止跨越对齐边界读。

比如你使用的指令是 32 位操作指令。你必须使内存地址为 32 位的倍数。否则可能出现 3 种情况:

1. 你的 CPU 支持非对齐访问(如 Intel 家族)。这时性能会降低。
2. 你的 CPU 不支持非对齐房屋,但编译器发现你在这么做,于是编译器将代码展开成两次读取,然后用位运算得出正确结果。性能降低。
3. 你的 CPU 不支持非对齐访问,同时因为你的写法的原因(考虑到使用 void *指针倒了一次编译器已经没法理解了),编译器不会采取额外操作,运行时,你的程序触发总线错误。

而 1 字节的 char 不会使用 32 位的读取指令读取,用的是 8 位操作的指令,没有位运算,它也不会用两个 CPU 周期。性能没有损失。而且,因为能更高效的利用 CPU 高速缓存,实际上性能会更好!对于编译器,除非有必要,编译器尽可能不把 char 扩充。
iwtbauh
2019-07-30 23:59:36 +08:00
@mason961125 #42

#16 “各种通信协议不用位运算麻烦死你”。

比如向总线发送 5 位的 a,10 位 b,15 位 c,6 自己校验和。这时候用位域的话就不用自己手写位运算填充了呀。
iwtbauh
2019-07-31 00:28:26 +08:00
乘 /除 2 的倍数时,我习惯写成移位

如果需要操作某种二进制协议 /文件格式时,我优先使用位域,但有时也会使用位运算

如果只是为了省内存,除非是极端情况(硬件条件极其恶劣或者运算强度需要压榨出机器最后一丝性能)拒绝使用。
iwtbauh
2019-07-31 00:30:29 +08:00
@iwtbauh #45 额,不是 2 的倍数,2^n,这叫什么,是幂吗,数学渣渣哭了
muzhidianzi
2019-07-31 00:48:37 +08:00
@jaskle 小白求大佬展开讲讲?还一直没思考过这个
muzhidianzi
2019-07-31 00:54:09 +08:00
@jaskle 才发现楼下有解释 尴尬 下次耐心看完再提问 多谢大佬点出问题所在
jaskle
2019-07-31 07:50:51 +08:00
@iwtbauh 准确的说 x86 确实有读取和写入单字节的指令,不过这并不代表他是个单周期指令,退 1w 步讲,内存条数据总线单周期最小读取是 4 个字节,当然不排除 cpu 缓存的存在。在单片机之类的环境表现尤为突出,当年使用某国产指纹芯片 as605 不对齐 cpu 竟然直接异常。st 系列好很多,但是在遇到跨页读取(通过强转读取通讯数据 buf 的 4 字节)仍然会出现读取数据错误(这个问题查了很久)。
当然这个话题并不是为了抬杠,而是想说明 uchar 作为布尔是没有任何意义的,所占用空间(编译器强制 4 对齐)和计算时间(≥1 个周期)都没有任何优势。
jaskle
2019-07-31 07:54:15 +08:00
对于位操作我的想法是看计算类型以及计算量,主要考虑到可读性和开发效率。如果对位计算有兴趣可以阅读一下 bitmap 算法相关书籍
ttgo
2019-07-31 08:00:11 +08:00
偶尔用一下,炫技。。
iwtbauh
2019-07-31 08:56:53 +08:00
@jaskle #49

“所占用空间(编译器强制 4 对齐)和计算时间(≥1 个周期)都没有任何优势。”

看#43:

“对于编译器,除非有必要,编译器尽可能不把 char 扩充。” 除非是没办法了,编译器是有多想不开才会把 char 对齐到 4 字节啊。

“它也不会用两个 CPU 周期。性能没有损失。而且,因为能更高效的利用 CPU 高速缓存,实际上性能会更好” 我反正没有见过哪个现代处理器是违反了这一条的,可能有很罕见的处理器上不一样吧。

不对齐访问异常很正常,比如 sun spark 就是这样的。但是不同的数据类型对齐要求不一样,char 没有对其要求,16 位的 short 要求按照 2 字节对齐,32 位的 int 要求 4 字节对齐,64 位的 long 要求 8 字节对齐。
szq8014
2019-07-31 09:09:37 +08:00
@jaskle 哈哈哈哈
monsterxx03
2019-07-31 09:29:04 +08:00
二进制协议解析肯定要用,比如之前写 dns 协议 parser 的时候.
bitmap 和相关变种算法里很常用, 比如 bloom filter, 你得先实现个 bit array 吧.
momocraft
2019-07-31 09:32:15 +08:00
如果语义一致(比如可 | & 复合) 用位运算是最自然的
Chowe
2019-07-31 09:48:27 +08:00
对不起我不仅用位运算我还各种 goto 外加直接访问物理内存:doge
inhzus
2019-07-31 09:49:06 +08:00
Golang 没有 enum 用位运算表示类型很正常吧…
Harv
2019-07-31 10:21:44 +08:00
开发时简单运算顺手就用,但一般是发布调试前统一改,统一优化。
至于你们说后期维护...一般都会把原式注释放后面的。如果不带注释,读起来是真的伤身体。
junbaor
2019-07-31 10:24:34 +08:00
代码是给人看的,顺便让机器执行一下。如果不是基础框架,并且性能瓶颈不在那一块,建议直接打死。😃
AlphaTr
2019-07-31 10:50:44 +08:00
不抵触,不滥用;优先保证语义的清晰;然后才考虑性能

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/587613

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX