mirror of
https://github.com/golang/go
synced 2024-11-21 19:24:45 -07:00
go spec: clarify rules for shifts
Note: This is not a spec change. The spec was not clear on the result type of constant shift expressions. Made it more explicit and added additional examples. Also: Remove paragraph on send expressions (they are statements, now). Fixes #1708. R=rsc, r, iant, r CC=golang-dev https://golang.org/cl/4517074
This commit is contained in:
parent
09dd5bf13b
commit
32d127823f
@ -1,5 +1,5 @@
|
|||||||
<!-- title The Go Programming Language Specification -->
|
<!-- title The Go Programming Language Specification -->
|
||||||
<!-- subtitle Version of May 15, 2011 -->
|
<!-- subtitle Version of May 23, 2011 -->
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
TODO
|
TODO
|
||||||
@ -10,7 +10,6 @@ TODO
|
|||||||
[ ] clarify what a field name is in struct declarations
|
[ ] clarify what a field name is in struct declarations
|
||||||
(struct{T} vs struct {T T} vs struct {t T})
|
(struct{T} vs struct {T T} vs struct {t T})
|
||||||
[ ] need explicit language about the result type of operations
|
[ ] need explicit language about the result type of operations
|
||||||
[ ] may want to have some examples for the types of shift operations
|
|
||||||
[ ] should string(1<<s) and float32(1<<s) be valid?
|
[ ] should string(1<<s) and float32(1<<s) be valid?
|
||||||
[ ] should probably write something about evaluation order of statements even
|
[ ] should probably write something about evaluation order of statements even
|
||||||
though obvious
|
though obvious
|
||||||
@ -2702,42 +2701,34 @@ unary_op = "+" | "-" | "!" | "^" | "*" | "&" | "<-" .
|
|||||||
<p>
|
<p>
|
||||||
Comparisons are discussed <a href="#Comparison_operators">elsewhere</a>.
|
Comparisons are discussed <a href="#Comparison_operators">elsewhere</a>.
|
||||||
For other binary operators, the operand types must be <a href="#Type_identity">identical</a>
|
For other binary operators, the operand types must be <a href="#Type_identity">identical</a>
|
||||||
unless the operation involves channels, shifts, or untyped <a href="#Constants">constants</a>.
|
unless the operation involves shifts or untyped <a href="#Constants">constants</a>.
|
||||||
For operations involving constants only, see the section on
|
For operations involving constants only, see the section on
|
||||||
<a href="#Constant_expressions">constant expressions</a>.
|
<a href="#Constant_expressions">constant expressions</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In a channel send, the first operand is always a channel and the second
|
Except for shift operations, if one operand is an untyped <a href="#Constants">constant</a>
|
||||||
must be a value <a href="#Assignability">assignable</a>
|
|
||||||
to the channel's element type.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Except for shift operations,
|
|
||||||
if one operand is an untyped <a href="#Constants">constant</a>
|
|
||||||
and the other operand is not, the constant is <a href="#Conversions">converted</a>
|
and the other operand is not, the constant is <a href="#Conversions">converted</a>
|
||||||
to the type of the other operand.
|
to the type of the other operand.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The right operand in a shift operation must have unsigned integer type
|
The right operand in a shift expression must have unsigned integer type
|
||||||
or be an untyped constant that can be converted to unsigned integer type.
|
or be an untyped constant that can be converted to unsigned integer type.
|
||||||
</p>
|
If the left operand of a non-constant shift expression is an untyped constant,
|
||||||
|
the type of the constant is what it would be if the shift expression were
|
||||||
<p>
|
replaced by its left operand alone.
|
||||||
If the left operand of a non-constant shift operation is an untyped constant,
|
|
||||||
the type of constant is what it would be if the shift operation were replaced by
|
|
||||||
the left operand alone.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
var s uint = 33
|
var s uint = 33
|
||||||
var i = 1<<s // 1 has type int
|
var i = 1<<s // 1 has type int
|
||||||
var j = int32(1<<s) // 1 has type int32; j == 0
|
var j int32 = 1<<s // 1 has type int32; j == 0
|
||||||
var u = uint64(1<<s) // 1 has type uint64; u == 1<<33
|
var k = uint64(1<<s) // 1 has type uint64; k == 1<<33
|
||||||
var f = float32(1<<s) // illegal: 1 has type float32, cannot shift
|
var m int = 1.0<<s // legal: 1.0 has type int
|
||||||
var g = float32(1<<33) // legal; 1<<33 is a constant shift operation; g == 1<<33
|
var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift
|
||||||
|
var v float32 = 1<<s // illegal: 1 has type float32, cannot shift
|
||||||
|
var w int64 = 1.0<<33 // legal: 1.0<<33 is a constant shift expression
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h3 id="Operator_precedence">Operator precedence</h3>
|
<h3 id="Operator_precedence">Operator precedence</h3>
|
||||||
@ -2869,8 +2860,8 @@ be replaced by a bitwise "and" operation:
|
|||||||
<p>
|
<p>
|
||||||
The shift operators shift the left operand by the shift count specified by the
|
The shift operators shift the left operand by the shift count specified by the
|
||||||
right operand. They implement arithmetic shifts if the left operand is a signed
|
right operand. They implement arithmetic shifts if the left operand is a signed
|
||||||
integer and logical shifts if it is an unsigned integer. The shift count must
|
integer and logical shifts if it is an unsigned integer.
|
||||||
be an unsigned integer. There is no upper limit on the shift count. Shifts behave
|
There is no upper limit on the shift count. Shifts behave
|
||||||
as if the left operand is shifted <code>n</code> times by 1 for a shift
|
as if the left operand is shifted <code>n</code> times by 1 for a shift
|
||||||
count of <code>n</code>.
|
count of <code>n</code>.
|
||||||
As a result, <code>x << 1</code> is the same as <code>x*2</code>
|
As a result, <code>x << 1</code> is the same as <code>x*2</code>
|
||||||
@ -3382,21 +3373,35 @@ respectively. Except for shift operations, if the operands of a binary operation
|
|||||||
are an untyped integer constant and an untyped floating-point constant,
|
are an untyped integer constant and an untyped floating-point constant,
|
||||||
the integer constant is converted to an untyped floating-point constant
|
the integer constant is converted to an untyped floating-point constant
|
||||||
(relevant for <code>/</code> and <code>%</code>).
|
(relevant for <code>/</code> and <code>%</code>).
|
||||||
Similarly,
|
Similarly, untyped integer or floating-point constants may be used as operands
|
||||||
untyped integer or floating-point constants may be used as operands
|
|
||||||
wherever it is legal to use an operand of complex type;
|
wherever it is legal to use an operand of complex type;
|
||||||
the integer or floating point constant is converted to a
|
the integer or floating point constant is converted to a
|
||||||
complex constant with a zero imaginary part.
|
complex constant with a zero imaginary part.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Applying an operator to untyped constants results in an untyped
|
A constant <a href="#Comparison_operators">comparison</a> always yields
|
||||||
|
a constant of type <code>bool</code>. If the left operand of a constant
|
||||||
|
<a href="#Operators">shift expression</a> is an untyped constant, the
|
||||||
|
result is an integer constant; otherwise it is a constant of the same
|
||||||
|
type as the left operand, which must be of integer type
|
||||||
|
(§<a href="#Arithmetic_operators">Arithmetic operators</a>).
|
||||||
|
Applying all other operators to untyped constants results in an untyped
|
||||||
constant of the same kind (that is, a boolean, integer, floating-point,
|
constant of the same kind (that is, a boolean, integer, floating-point,
|
||||||
complex, or string constant), except for
|
complex, or string constant).
|
||||||
<a href="#Comparison_operators">comparison operators</a>, which result in
|
|
||||||
a constant of type <code>bool</code>.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
const a = 2 + 3.0 // a == 5.0 (floating-point constant)
|
||||||
|
const b = 15 / 4 // b == 3 (integer constant)
|
||||||
|
const c = 15 / 4.0 // c == 3.75 (floating-point constant)
|
||||||
|
const d = 1 << 3.0 // d == 8 (integer constant)
|
||||||
|
const e = 1.0 << 3 // e == 8 (integer constant)
|
||||||
|
const f = int32(1) << 33 // f == 0 (type int32)
|
||||||
|
const g = float64(2) >> 1 // illegal (float64(2) is a typed floating-point constant)
|
||||||
|
const h = "foo" > "bar" // h == true (type bool)
|
||||||
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Imaginary literals are untyped complex constants (with zero real part)
|
Imaginary literals are untyped complex constants (with zero real part)
|
||||||
and may be combined in binary
|
and may be combined in binary
|
||||||
|
Loading…
Reference in New Issue
Block a user