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

Go 扫描程序包中的text/scanner/scanner.go使用技巧来查找空格:


const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '

接着:


// skip white space

for s.Whitespace&(1<<uint(ch)) != 0 {

    ch = s.next()

}

由于字符值左移超过 31,是否存在不唯一的情况?我的意思是,当某些字符与制表符模 32 相同时,它会被识别为空格吗?


临摹微笑
浏览 208回答 2
2回答

精慕HU

正如规范中提到的,这<<是一个移位操作:移位运算符将左操作数移位右操作数指定的移位计数。如果左操作数是有符号整数,则它们实现算术移位,如果它是无符号整数,则它们实现逻辑移位。班次计数没有上限。移位的行为就像左操作数被移位 n 次,移位计数为 n。因此,x << 1 与 x*2 相同,x >> 1 与 x/2 相同,但向负无穷大截断。对于较大的值ch,1<<uint(ch)将导致溢出:对于无符号整数值,运算 +、-、* 和 << 是以 2&nbsp;n为模计算的,其中 n 是无符号整数类型的位宽。粗略地说,这些无符号整数运算在溢出时丢弃高位,并且程序可能依赖于“环绕”。对于有符号整数,运算 +、-、* 和 << 可能会合法溢出并且结果值存在并且由有符号整数表示、运算及其操作数确定性地定义。不会因溢出而引发异常。在不发生溢出的假设下,编译器可能不会优化代码。例如,它可能不会假设 x < x + 1 总是正确的。因此<<,使用按位旋转运算符(您似乎正在描述的内容)实现将违反规范。&nbsp;1<<uint(ch)对于ch大于int类型大小的值,将评估为零,因此不会导致任何误报。

慕丝7291255

完整回答:规范明确指出,对于无符号操作,我们将高位屏蔽掉,因此低位实际上是“环绕”的。它起作用的原因是:Scanner.Whitespace实际上uint64是GoWhitespace完全合身的价值运行时s.Whitespace&(1<<uint(ch))对无符号整数的操作可以具有任意大的中间值并且会回绕。因此,如果说 char 是“a”(96),我们有1 << 96溢出所以 64 位 int 的模大小为 0。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go