mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #5772 from ethereum/docs-split-conversion
[DOCS] Split conversion sections into new doc
This commit is contained in:
commit
6d4d0a5308
128
docs/types.rst
128
docs/types.rst
@ -83,130 +83,4 @@ each ``_KeyType``, recursively. For example with a mapping:
|
||||
|
||||
.. include:: types/operators.rst
|
||||
|
||||
.. index:: ! type;conversion, ! cast
|
||||
|
||||
.. _types-conversion-elementary-types:
|
||||
|
||||
Conversions between Elementary Types
|
||||
====================================
|
||||
|
||||
Implicit Conversions
|
||||
--------------------
|
||||
|
||||
If an operator is applied to different types, the compiler tries to
|
||||
implicitly convert one of the operands to the type of the other (the same is
|
||||
true for assignments). In general, an implicit conversion between value-types
|
||||
is possible if it
|
||||
makes sense semantically and no information is lost: ``uint8`` is convertible to
|
||||
``uint16`` and ``int128`` to ``int256``, but ``int8`` is not convertible to ``uint256``
|
||||
(because ``uint256`` cannot hold e.g. ``-1``).
|
||||
|
||||
For more details, please consult the sections about the types themselves.
|
||||
|
||||
Explicit Conversions
|
||||
--------------------
|
||||
|
||||
If the compiler does not allow implicit conversion but you know what you are
|
||||
doing, an explicit type conversion is sometimes possible. Note that this may
|
||||
give you some unexpected behaviour and allows you to bypass some security
|
||||
features of the compiler, so be sure to test that the
|
||||
result is what you want! Take the following example where you are converting
|
||||
a negative ``int8`` to a ``uint``:
|
||||
|
||||
::
|
||||
|
||||
int8 y = -3;
|
||||
uint x = uint(y);
|
||||
|
||||
At the end of this code snippet, ``x`` will have the value ``0xfffff..fd`` (64 hex
|
||||
characters), which is -3 in the two's complement representation of 256 bits.
|
||||
|
||||
If an integer is explicitly converted to a smaller type, higher-order bits are
|
||||
cut off::
|
||||
|
||||
uint32 a = 0x12345678;
|
||||
uint16 b = uint16(a); // b will be 0x5678 now
|
||||
|
||||
If an integer is explicitly converted to a larger type, it is padded on the left (i.e. at the higher order end).
|
||||
The result of the conversion will compare equal to the original integer::
|
||||
|
||||
uint16 a = 0x1234;
|
||||
uint32 b = uint32(a); // b will be 0x00001234 now
|
||||
assert(a == b);
|
||||
|
||||
Fixed-size bytes types behave differently during conversions. They can be thought of as
|
||||
sequences of individual bytes and converting to a smaller type will cut off the
|
||||
sequence::
|
||||
|
||||
bytes2 a = 0x1234;
|
||||
bytes1 b = bytes1(a); // b will be 0x12
|
||||
|
||||
If a fixed-size bytes type is explicitly converted to a larger type, it is padded on
|
||||
the right. Accessing the byte at a fixed index will result in the same value before and
|
||||
after the conversion (if the index is still in range)::
|
||||
|
||||
bytes2 a = 0x1234;
|
||||
bytes4 b = bytes4(a); // b will be 0x12340000
|
||||
assert(a[0] == b[0]);
|
||||
assert(a[1] == b[1]);
|
||||
|
||||
Since integers and fixed-size byte arrays behave differently when truncating or
|
||||
padding, explicit conversions between integers and fixed-size byte arrays are only allowed,
|
||||
if both have the same size. If you want to convert between integers and fixed-size byte arrays of
|
||||
different size, you have to use intermediate conversions that make the desired truncation and padding
|
||||
rules explicit::
|
||||
|
||||
bytes2 a = 0x1234;
|
||||
uint32 b = uint16(a); // b will be 0x00001234
|
||||
uint32 c = uint32(bytes4(a)); // c will be 0x12340000
|
||||
uint8 d = uint8(uint16(a)); // d will be 0x34
|
||||
uint8 e = uint8(bytes1(a)); // e will be 0x12
|
||||
|
||||
.. _types-conversion-literals:
|
||||
|
||||
Conversions between Literals and Elementary Types
|
||||
=================================================
|
||||
|
||||
Integer Types
|
||||
-------------
|
||||
|
||||
Decimal and hexadecimal number literals can be implicitly converted to any integer type
|
||||
that is large enough to represent it without truncation::
|
||||
|
||||
uint8 a = 12; // fine
|
||||
uint32 b = 1234; // fine
|
||||
uint16 c = 0x123456; // fails, since it would have to truncate to 0x3456
|
||||
|
||||
Fixed-Size Byte Arrays
|
||||
----------------------
|
||||
|
||||
Decimal number literals cannot be implicitly converted to fixed-size byte arrays. Hexadecimal
|
||||
number literals can be, but only if the number of hex digits exactly fits the size of the bytes
|
||||
type. As an exception both decimal and hexadecimal literals which have a value of zero can be
|
||||
converted to any fixed-size bytes type::
|
||||
|
||||
bytes2 a = 54321; // not allowed
|
||||
bytes2 b = 0x12; // not allowed
|
||||
bytes2 c = 0x123; // not allowed
|
||||
bytes2 d = 0x1234; // fine
|
||||
bytes2 e = 0x0012; // fine
|
||||
bytes4 f = 0; // fine
|
||||
bytes4 g = 0x0; // fine
|
||||
|
||||
String literals and hex string literals can be implicitly converted to fixed-size byte arrays,
|
||||
if their number of characters matches the size of the bytes type::
|
||||
|
||||
bytes2 a = hex"1234"; // fine
|
||||
bytes2 b = "xy"; // fine
|
||||
bytes2 c = hex"12"; // not allowed
|
||||
bytes2 d = hex"123"; // not allowed
|
||||
bytes2 e = "x"; // not allowed
|
||||
bytes2 f = "xyz"; // not allowed
|
||||
|
||||
Addresses
|
||||
---------
|
||||
|
||||
As described in :ref:`address_literals`, hex literals of the correct size that pass the checksum
|
||||
test are of ``address`` type. No other literals can be implicitly converted to the ``address`` type.
|
||||
|
||||
Explicit conversions from ``bytes20`` or any integer type to ``address`` result in ``address payable``.
|
||||
.. include:: types/conversion.rst
|
127
docs/types/conversion.rst
Normal file
127
docs/types/conversion.rst
Normal file
@ -0,0 +1,127 @@
|
||||
.. index:: ! type;conversion, ! cast
|
||||
|
||||
.. _types-conversion-elementary-types:
|
||||
|
||||
Conversions between Elementary Types
|
||||
====================================
|
||||
|
||||
Implicit Conversions
|
||||
--------------------
|
||||
|
||||
If an operator is applied to different types, the compiler tries to
|
||||
implicitly convert one of the operands to the type of the other (the same is
|
||||
true for assignments). In general, an implicit conversion between value-types
|
||||
is possible if it
|
||||
makes sense semantically and no information is lost: ``uint8`` is convertible to
|
||||
``uint16`` and ``int128`` to ``int256``, but ``int8`` is not convertible to ``uint256``
|
||||
(because ``uint256`` cannot hold e.g. ``-1``).
|
||||
|
||||
For more details, please consult the sections about the types themselves.
|
||||
|
||||
Explicit Conversions
|
||||
--------------------
|
||||
|
||||
If the compiler does not allow implicit conversion but you know what you are
|
||||
doing, an explicit type conversion is sometimes possible. Note that this may
|
||||
give you some unexpected behaviour and allows you to bypass some security
|
||||
features of the compiler, so be sure to test that the
|
||||
result is what you want! Take the following example where you are converting
|
||||
a negative ``int8`` to a ``uint``:
|
||||
|
||||
::
|
||||
|
||||
int8 y = -3;
|
||||
uint x = uint(y);
|
||||
|
||||
At the end of this code snippet, ``x`` will have the value ``0xfffff..fd`` (64 hex
|
||||
characters), which is -3 in the two's complement representation of 256 bits.
|
||||
|
||||
If an integer is explicitly converted to a smaller type, higher-order bits are
|
||||
cut off::
|
||||
|
||||
uint32 a = 0x12345678;
|
||||
uint16 b = uint16(a); // b will be 0x5678 now
|
||||
|
||||
If an integer is explicitly converted to a larger type, it is padded on the left (i.e. at the higher order end).
|
||||
The result of the conversion will compare equal to the original integer::
|
||||
|
||||
uint16 a = 0x1234;
|
||||
uint32 b = uint32(a); // b will be 0x00001234 now
|
||||
assert(a == b);
|
||||
|
||||
Fixed-size bytes types behave differently during conversions. They can be thought of as
|
||||
sequences of individual bytes and converting to a smaller type will cut off the
|
||||
sequence::
|
||||
|
||||
bytes2 a = 0x1234;
|
||||
bytes1 b = bytes1(a); // b will be 0x12
|
||||
|
||||
If a fixed-size bytes type is explicitly converted to a larger type, it is padded on
|
||||
the right. Accessing the byte at a fixed index will result in the same value before and
|
||||
after the conversion (if the index is still in range)::
|
||||
|
||||
bytes2 a = 0x1234;
|
||||
bytes4 b = bytes4(a); // b will be 0x12340000
|
||||
assert(a[0] == b[0]);
|
||||
assert(a[1] == b[1]);
|
||||
|
||||
Since integers and fixed-size byte arrays behave differently when truncating or
|
||||
padding, explicit conversions between integers and fixed-size byte arrays are only allowed,
|
||||
if both have the same size. If you want to convert between integers and fixed-size byte arrays of
|
||||
different size, you have to use intermediate conversions that make the desired truncation and padding
|
||||
rules explicit::
|
||||
|
||||
bytes2 a = 0x1234;
|
||||
uint32 b = uint16(a); // b will be 0x00001234
|
||||
uint32 c = uint32(bytes4(a)); // c will be 0x12340000
|
||||
uint8 d = uint8(uint16(a)); // d will be 0x34
|
||||
uint8 e = uint8(bytes1(a)); // e will be 0x12
|
||||
|
||||
.. _types-conversion-literals:
|
||||
|
||||
Conversions between Literals and Elementary Types
|
||||
=================================================
|
||||
|
||||
Integer Types
|
||||
-------------
|
||||
|
||||
Decimal and hexadecimal number literals can be implicitly converted to any integer type
|
||||
that is large enough to represent it without truncation::
|
||||
|
||||
uint8 a = 12; // fine
|
||||
uint32 b = 1234; // fine
|
||||
uint16 c = 0x123456; // fails, since it would have to truncate to 0x3456
|
||||
|
||||
Fixed-Size Byte Arrays
|
||||
----------------------
|
||||
|
||||
Decimal number literals cannot be implicitly converted to fixed-size byte arrays. Hexadecimal
|
||||
number literals can be, but only if the number of hex digits exactly fits the size of the bytes
|
||||
type. As an exception both decimal and hexadecimal literals which have a value of zero can be
|
||||
converted to any fixed-size bytes type::
|
||||
|
||||
bytes2 a = 54321; // not allowed
|
||||
bytes2 b = 0x12; // not allowed
|
||||
bytes2 c = 0x123; // not allowed
|
||||
bytes2 d = 0x1234; // fine
|
||||
bytes2 e = 0x0012; // fine
|
||||
bytes4 f = 0; // fine
|
||||
bytes4 g = 0x0; // fine
|
||||
|
||||
String literals and hex string literals can be implicitly converted to fixed-size byte arrays,
|
||||
if their number of characters matches the size of the bytes type::
|
||||
|
||||
bytes2 a = hex"1234"; // fine
|
||||
bytes2 b = "xy"; // fine
|
||||
bytes2 c = hex"12"; // not allowed
|
||||
bytes2 d = hex"123"; // not allowed
|
||||
bytes2 e = "x"; // not allowed
|
||||
bytes2 f = "xyz"; // not allowed
|
||||
|
||||
Addresses
|
||||
---------
|
||||
|
||||
As described in :ref:`address_literals`, hex literals of the correct size that pass the checksum
|
||||
test are of ``address`` type. No other literals can be implicitly converted to the ``address`` type.
|
||||
|
||||
Explicit conversions from ``bytes20`` or any integer type to ``address`` result in ``address payable``.
|
Loading…
Reference in New Issue
Block a user