-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Move type related FAQ points #4499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,12 +6,11 @@ | |
Types | ||
***** | ||
|
||
Solidity is a statically typed language, which means that the type of each | ||
variable (state and local) needs to be specified. | ||
Solidity provides several elementary types which can be combined to form complex types. | ||
Solidity is a statically typed language, which means that you need to specify the type of each variable (state and local). Solidity provides elementary types which you can combine to form complex types. | ||
|
||
In addition, types can interact with each other in expressions containing | ||
operators. For a quick reference of the various operators, see :ref:`order`. | ||
Types can interact in expressions containing operators. For a quick reference of the various operators, see :ref:`order`. | ||
|
||
The concept of "undefined" or "null" values do not exist in Solidity. To handle any unexpected values, you should use ``revert("Error message")`` to revert the whole transaction. | ||
|
||
.. index:: ! value type, ! type;value | ||
|
||
|
@@ -52,6 +51,12 @@ Operators: | |
* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation) | ||
* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation), ``<<`` (left shift), ``>>`` (right shift) | ||
|
||
The bit size of an unsigned integer determines its range, for example, for ``uint256``, this is 0 up to 2 :sup:`256` -1. If the result of an operation doesn't fit inside this range, it is truncated. Not taking these truncations into account can have `serious consequences <https://en.bitcoin.it/wiki/Value_overflow_incident>`_. For example, the code below checks to see if the balance plus a value is actually greater than or equal to the original value. | ||
|
||
:: | ||
|
||
require((balanceOf[_to] + _value) >= balanceOf[_to]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is a bad idea without explanation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @axic I thought the text above and the example were enough, but added a little more, hopefully I got it right. |
||
|
||
Division always truncates (it is just compiled to the ``DIV`` opcode of the EVM), but it does not truncate if both | ||
operators are :ref:`literals<rational_literals>` (or literal expressions). | ||
|
||
|
@@ -296,16 +301,28 @@ a non-rational number). | |
uint128 a = 1; | ||
uint128 b = 2.5 + a + 0.5; | ||
|
||
.. index:: literal, literal;string, string | ||
.. index:: literal, literal;string, string, string length, string size | ||
|
||
String Literals | ||
String Literals and Types | ||
--------------- | ||
|
||
String literals are written with either double or single-quotes (``"foo"`` or ``'bar'``). They do not imply trailing zeroes as in C; ``"foo"`` represents three bytes not four. As with integer literals, their type can vary, but they are implicitly convertible to ``bytes1``, ..., ``bytes32``, if they fit, to ``bytes`` and to ``string``. | ||
String literals are written with either double or single-quotes (``"foo"`` or ``'bar'``). They do not imply trailing zeroes as in C; ``"foo"`` represents three bytes not four. As with integer literals, their type can vary, but they are implicitly convertible from ``bytes1`` through ``bytes32``, if they fit, and to ``bytes`` and to ``string``. For example, with :: | ||
|
||
"stringliteral"; | ||
|
||
The string literal is interpreted in its raw byte form and with certain tools, if you inspect ``somevar``, you see a 32-byte hex value, which is the ``"stringliteral"`` in hex. | ||
|
||
String literals support escape characters, such as ``\n`` for line breaks, ``\xNN`` and ``\uNNNN`` for special characters. ``\xNN`` takes a hex value and inserts the appropriate character, while ``\uNNNN`` takes a Unicode codepoint and inserts an UTF-8 character. | ||
|
||
|
||
String Types | ||
^^^^^^^^^^^^ | ||
|
||
String literals support escape characters, such as ``\n``, ``\xNN`` and ``\uNNNN``. ``\xNN`` takes a hex value and inserts the appropriate byte, while ``\uNNNN`` takes a Unicode codepoint and inserts an UTF-8 sequence. | ||
A string literal becomes a ``string`` type when you assign it to a variable, for example:: | ||
|
||
.. index:: literal, bytes | ||
bytes32 samevar = "stringliteral"; | ||
|
||
A ``string`` type is basically identical to ``bytes``, but it is assumed to hold the UTF-8 encoding of a real string. Since ``string`` UTF-8 encoding of some characters takes more than a single byte, it is quite expensive to compute the number of characters in the string. Because of this, Solidity does not support length methods ``string s; s.length``, or accessing an item at an array index ``s[2]``. If you want to access the low-level byte encoding of the string, you can use ``bytes(s).length`` and ``bytes(s)[2]`` which returns the number of bytes in the UTF-8 encoding of the string (not the number of characters) and the second byte (not character) of the UTF-8 encoded string, respectively. | ||
|
||
Hexadecimal Literals | ||
-------------------- | ||
|
@@ -321,9 +338,8 @@ Hexademical Literals behave like String Literals and have the same convertibilit | |
Enums | ||
----- | ||
|
||
Enums are one way to create a user-defined type in Solidity. They are explicitly convertible | ||
to and from all integer types but implicit conversion is not allowed. The explicit conversions | ||
check the value ranges at runtime and a failure causes an exception. Enums needs at least one member. | ||
Enums are one way to create a user-defined type in Solidity. They are explicitly convertible to and from all integer types but implicit conversion is not allowed. The explicit conversions check the value ranges at runtime and a failure causes an exception. Enums need at least one member. | ||
|
||
|
||
:: | ||
|
||
|
@@ -582,10 +598,7 @@ Default data location: | |
Arrays | ||
------ | ||
|
||
Arrays can have a compile-time fixed size or they can be dynamic. | ||
For storage arrays, the element type can be arbitrary (i.e. also other | ||
arrays, mappings or structs). For memory arrays, it cannot be a mapping and | ||
has to be an ABI type if it is an argument of a publicly-visible function. | ||
Arrays can have a compile-time fixed size or they can be dynamic. For storage arrays, the element type can be arbitrary (i.e. also other arrays, mappings or structs). For memory arrays, it cannot be a mapping and has to be an ABI type if it is an argument of a publicly-visible function. | ||
|
||
An array of fixed size ``k`` and element type ``T`` is written as ``T[k]``, | ||
an array of dynamic size as ``T[]``. As an example, an array of 5 dynamic | ||
|
@@ -680,15 +693,27 @@ possible: | |
It is planned to remove this restriction in the future but currently creates | ||
some complications because of how arrays are passed in the ABI. | ||
|
||
You can initialise a statically sized memory array inline using syntax such as ``string[] memory myarray = new string[](4);``. For example:: | ||
|
||
pragma solidity ^0.4.16; | ||
|
||
contract C { | ||
function f() public pure returns (uint8[5]) { | ||
string[4] memory adaArr = ["This", "is", "an", "array"]; | ||
return [1, 2, 3, 4, 5]; | ||
} | ||
} | ||
|
||
You can create and initialise multi-dimensional arrays in the same ways, but filling arrays can cost a lot of gas, so make sure you optimise how you use them. | ||
|
||
.. index:: ! array;length, length, push, pop, !array;push, !array;pop | ||
|
||
Members | ||
^^^^^^^ | ||
|
||
**length**: | ||
Arrays have a ``length`` member to hold their number of elements. | ||
Dynamic arrays can be resized in storage (not in memory) by changing the | ||
``.length`` member. This does not happen automatically when attempting to access elements outside the current length. The size of memory arrays is fixed (but dynamic, i.e. it can depend on runtime parameters) once they are created. | ||
You can resize dynamic arrays in storage (**not in memory**) by changing the ``.length`` member. This does not happen automatically when attempting to access elements outside the current length. The size of memory arrays is fixed (but dynamic, i.e. it can depend on runtime parameters) once they are created. If you try to resize a non dynamic array that isn't in storage, you receive a ``Value must be an lvalue`` error. | ||
**push**: | ||
Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``push`` that can be used to append an element at the end of the array. The function returns the new length. | ||
**pop**: | ||
|
@@ -827,22 +852,14 @@ shown in the following example: | |
} | ||
|
||
The contract does not provide the full functionality of a crowdfunding | ||
contract, but it contains the basic concepts necessary to understand structs. | ||
Struct types can be used inside mappings and arrays and they can itself | ||
contain mappings and arrays. | ||
contract, but it contains the basic concepts necessary to understand structs. Struct types can be used inside mappings and arrays and they can itself contain mappings and arrays. | ||
|
||
It is not possible for a struct to contain a member of its own type, | ||
although the struct itself can be the value type of a mapping member. | ||
This restriction is necessary, as the size of the struct has to be finite. | ||
It is not possible for a struct to contain a member of its own type, although the struct itself can be the value type of a mapping member. This restriction is necessary, as the size of the struct has to be finite. | ||
|
||
Note how in all the functions, a struct type is assigned to a local variable | ||
(of the default storage data location). | ||
This does not copy the struct but only stores a reference so that assignments to | ||
members of the local variable actually write to the state. | ||
...note:: | ||
All the functions above assign a ``struct`` type to a local variable (of the default storage data location). This does not copy the ``struct`` but only stores a reference so that assignments to members of the local variable actually write to the state. | ||
|
||
Of course, you can also directly access the members of the struct without | ||
assigning it to a local variable, as in | ||
``campaigns[campaignID].amount = 0``. | ||
You can also directly access the members of the struct without assigning it to a local variable, as in ``campaigns[campaignID].amount = 0``. | ||
|
||
.. index:: !mapping | ||
|
||
|
@@ -984,3 +1001,4 @@ converted to a matching size. This makes alignment and padding explicit:: | |
bytes32(uint256(x)); // pad on the left | ||
bytes32(bytes2(x)); // pad on the right | ||
|
||
.. index:: ! type;deduction, ! var |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only works for checking overflow for unsigned types, so we should make that clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done