为了账号安全,请及时绑定邮箱和手机立即绑定

去扫描仪 - 空白的正确性?

去扫描仪 - 空白的正确性?

Go
临摹微笑 2021-07-28 10:53:47
Go 扫描程序包中的text/scanner/scanner.go使用技巧来查找空格:const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '接着:// skip white spacefor s.Whitespace&(1<<uint(ch)) != 0 {    ch = s.next()}由于字符值左移超过 31,是否存在不唯一的情况?我的意思是,当某些字符与制表符模 32 相同时,它会被识别为空格吗?
查看完整描述

2 回答

?
精慕HU

TA贡献1845条经验 获得超8个赞

正如规范中提到,这<<是一个移位操作:

移位运算符将左操作数移位右操作数指定的移位计数。如果左操作数是有符号整数,则它们实现算术移位,如果它是无符号整数,则它们实现逻辑移位。班次计数没有上限。移位的行为就像左操作数被移位 n 次,移位计数为 n。因此,x << 1 与 x*2 相同,x >> 1 与 x/2 相同,但向负无穷大截断。

对于较大的值ch1<<uint(ch)导致溢出

对于无符号整数值,运算 +、-、* 和 << 是以 2 n为模计算的,其中 n 是无符号整数类型的位宽。粗略地说,这些无符号整数运算在溢出时丢弃高位,并且程序可能依赖于“环绕”。

对于有符号整数,运算 +、-、* 和 << 可能会合法溢出并且结果值存在并且由有符号整数表示、运算及其操作数确定性地定义。不会因溢出而引发异常。在不发生溢出的假设下,编译器可能不会优化代码。例如,它可能不会假设 x < x + 1 总是正确的。

因此<<,使用按位旋转运算符(您似乎正在描述的内容)实现将违反规范。 1<<uint(ch)对于ch大于int类型大小的值,将评估为零,因此不会导致任何误报。


查看完整回答
反对 回复 2021-08-02
?
慕丝7291255

TA贡献1859条经验 获得超6个赞

完整回答:

规范明确指出,对于无符号操作,我们将高位屏蔽掉,因此低位实际上是“环绕”的。

它起作用的原因是:

  1. Scanner.Whitespace实际上uint64GoWhitespace完全合身的价值

  2. 运行时s.Whitespace&(1<<uint(ch))对无符号整数的操作可以具有任意大的中间值并且会回绕。因此,如果说 char 是“a”(96),我们有1 << 96溢出所以 64 位 int 的模大小为 0。


查看完整回答
反对 回复 2021-08-02
  • 2 回答
  • 0 关注
  • 205 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信