# Primitive types and operators

TODO int/uint -> isuze/usize

Rust has pretty much the same arithmetic and logical operators as C++. `bool`

is
the same in both languages (as are the `true`

and `false`

literals). Rust has
similar concepts of integers, unsigned integers, and floats. However the syntax
is a bit different. Rust uses `int`

to mean an integer and `uint`

to mean an
unsigned integer. These types are pointer sized. E.g., on a 32 bit system,
`uint`

means a 32 bit unsigned integer. Rust also has explicitly sized types
which are `u`

or `i`

followed by 8, 16, 32, or 64. So, for example, `u8`

is an 8
bit unsigned integer and `i32`

is a 32 bit signed integer. For floats, Rust has
`f32`

and `f64`

.

Numeric literals can take suffixes to indicate their type (using `i`

and `u`

instead of `int`

and `uint`

). If no suffix is given, Rust tries to infer the
type. If it can't infer, it uses `int`

or `f64`

(if there is a decimal point).
Examples:

```
fn main() {
let x: bool = true;
let x = 34; // type int
let x = 34u; // type uint
let x: u8 = 34u8;
let x = 34i64;
let x = 34f32;
}
```

As a side note, Rust lets you redefine variables so the above code is legal -
each `let`

statement creates a new variable `x`

and hides the previous one. This
is more useful than you might expect due to variables being immutable by
default.

Numeric literals can be given as binary, octal, and hexadecimal, as well as
decimal. Use the `0b`

, `0o`

, and `0x`

prefixes, respectively. You can use an
underscore anywhere in a numeric literal and it will be ignored. E.g,

```
fn main() {
let x = 12;
let x = 0b1100;
let x = 0o14;
let x = 0xe;
let y = 0b_1100_0011_1011_0001;
}
```

Rust has chars and strings, but since they are Unicode, they are a bit different from C++. I'm going to postpone talking about them until after I've introduced pointers, references, and vectors (arrays).

Rust does not implicitly coerce numeric types. In general, Rust has much less
implicit coercion and subtyping than C++. Rust uses the `as`

keyword for
explicit coercions and casting. Any numeric value can be cast to another numeric
type. `as`

cannot be used to convert between booleans and numeric types. E.g.,

```
fn main() {
let x = 34u as int; // cast unsigned int to int
let x = 10 as f32; // int to float
let x = 10.45f64 as i8; // float to int (loses precision)
let x = 4u8 as u64; // gains precision
let x = 400u16 as u8; // 144, loses precision (and thus changes the value)
println!("`400u16 as u8` gives {}", x);
let x = -3i8 as u8; // 253, signed to unsigned (changes sign)
println!("`-3i8 as u8` gives {}", x);
//let x = 45u as bool; // FAILS!
}
```

Rust has the following numeric operators: `+`

, `-`

, `*`

, `/`

, `%`

; bitwise
operators: `|`

, `&`

, `^`

, `<<`

, `>>`

; comparison operators: `==`

, `!=`

, `>`

,
`<`

, `>=`

, `<=`

; short-circuit logical operators: `||`

, `&&`

. All of these
behave as in C++, however, Rust is a bit stricter about the types the operators
can be applied to - the bitwise operators can only be applied to integers and
the logical operators can only be applied to booleans. Rust has the `-`

unary
operator which negates a number. The `!`

operator negates a boolean and inverts
every bit on an integer type (equivalent to `~`

in C++ in the latter case). Rust
has compound assignment operators as in C++, e.g., `+=`

, but does not have
increment or decrement operators (e.g., `++`

).