Literals and operators

Literals: Fixed values written directly in code that you can tell at a glance. They are the most basic way to represent data in programs.

Their values stay constant and are hardcoded into the code, never changing while the program runs. No extra calculations or variable parsing are needed — they are literally the values you see.

For example, 13 and 3.14 shown below are literals, also known as literal values in other programming languages.

fn main() {
    println!("{}", 13);
    println!("{}", 3.14);
}Code language: JavaScript (javascript)

To make learning easier, the official team provides a free online Rust editor. You can learn basic Rust syntax directly on this tool without setting up a local environment. Click the link below.

Rust Playground

Literals

Rust supports literals of these types: integers, floating-point numbers, characters, strings, booleans and the unit type.

  • Integers: 11
  • Characters: 'a' (single quotes)
  • Strings: "abc" (double quotes)
  • Booleans: true / false
  • Unit type: ()

Different Bases for Integers

We use prefixes to distinguish number bases, which only apply to integers:

  • Hexadecimal: starts with 0x, example: 0x1F
  • Octal: starts with 0o, example: 0o77
  • Binary: starts with 0b, example: 0b1010

Digit Separators

You can insert underscores _ inside numeric literals to boost readability. These symbols do not affect the actual value:

  • Integers: 1_000 = 1000
  • Floating-point numbers: 0.000_001 = 0.000001

Scientific Notation

Floating-point numbers support scientific notation with E, and the default type is f64:

  • 1e6 = 1000000
  • 7.6e-4 = 0.00076

Literal Type Suffixes (Key Points)

Rust requires you to specify literal types clearly. Here are the common suffixes:

  • u32: 32-bit unsigned integer (non-negative numbers only)
  • i32: 32-bit signed integer (supports positive and negative values)

Note: Mixing signed and unsigned integers in calculations will cause errors.

Examples

fn main() {
    // 1. Regular integer literals
    println!("Integer: {}", 13);
    // Binary, octal and hexadecimal integers
    println!("Binary: {}", 0b1010);
    println!("Octal: {}", 0o77);
    println!("Hexadecimal: {}", 0x2A);
    // Integers with separators for better readability
    println!("Integer with underscores: {}", 1_000_000);
    // Integers with type suffixes
    println!("u32 unsigned integer: {}", 100u32);
    println!("i32 signed integer: {}", -50i32);

    // 2. Floating-point literals
    println!("Float: {}", 3.14);
    // Floating-point numbers with underscores
    println!("Float with underscores: {}", 0.000_001);
    // Floating-point numbers in scientific notation
    println!("Scientific notation: {}", 1e6);
    println!("Negative scientific notation: {}", 7.6e-4);

    // 3. String literals (double quotes)
    println!("String: {}", "hello world");

    // 4. Character literals (single quotes, single character only)
    println!("Character: {}", 'a');
    println!("Chinese character: {}", '中');

    // 5. Boolean literals
    println!("Boolean true: {}", true);
    println!("Boolean false: {}", false);

    // 6. Unit literal () (Rust unit type)
    println!("Unit type: {:?}", ());
}Code language: JavaScript (javascript)

Operators

Rust follows nearly the same rules and operator precedence as C-style languages.

1. Arithmetic Operators

Basic calculations like addition and subtraction, used together with integer type suffixes:

  • Addition: +
  • Subtraction: -

2. Boolean Logical Operators (Short-circuit Logic)

These operators only work with boolean values true/false:

  • AND &&: Returns true only when both sides are true
  • OR ||: Returns true if either side is true
  • NOT !: Inverts the boolean value
Expression Result
true && true true
true && false false
false && true false
false && false false
true || true true
true || false true
false || true true
false || false false
!true false
!false true

3. Bitwise Operators (Manipulate Binary Bits)

Mainly used for integers. We use {:04b} in examples to format output as 4-digit binary numbers:

  1. Bitwise AND &: Output 1 only if both corresponding bits are 1
  2. Bitwise OR |: Output 1 if either corresponding bit is 1
  3. Bitwise XOR ^: Output 1 if corresponding bits are different, otherwise 0
  4. Left Shift <<: Shift all binary bits to the left (equivalent to multiplying by 2ⁿ)
  5. Right Shift >>: Shift all binary bits to the right (equivalent to dividing by 2ⁿ)
  0 0 1 1
& 0 1 0 1
-----------
  0 0 0 1  

  0 0 1 1
| 0 1 0 1
-----------
  0 1 1 1

  0 0 1 1
^ 0 1 0 1
-----------
  0 1 1 0

Left Shift <<
Binary: 00000001
Shift left by 5 bits → 00100000, Result = 32

Right Shift >>
0x80 Binary: 10000000
Shift right by 2 bits → 00100000 (Hex 0x20), Result = 32
fn main() {
    // ========== Arithmetic Operators ==========
    // Integer addition: u32 means 32-bit unsigned integer
    // Output: 1 + 2 = 3
    println!("1 + 2 = {}", 1u32 + 2);

    // Integer subtraction: i32 means 32-bit signed integer, supports negative numbers
    // Changing to 1u32 will cause an error, unsigned integers cannot represent negatives
    // Output: 1 - 2 = -1
    println!("1 - 2 = {}", 1i32 - 2);

    // ========== Floating-point Literals - Scientific Notation ==========
    // Output: 1e4 equals 10000, -2.5e-3 equals -0.0025
    println!("1e4 = {}, -2.5e-3 = {}", 1e4, -2.5e-3);

    // ========== Boolean Logical Operators (Short-circuit) ==========
    // Logical AND &&: Returns true only when both values are true
    // Output: true AND false = false
    println!("true AND false = {}", true && false);

    // Logical OR ||: Returns true if either value is true
    // Output: true OR false = true
    println!("true OR false = {}", true || false);

    // Logical NOT !: Invert boolean value
    // Output: NOT true = false
    println!("NOT true = {}", !true);

    // ========== Bitwise Operators ==========
    // {:04b} prints 4-digit binary, pad with leading zeros if needed
    // Bitwise AND &: Result bit is 1 only when both bits are 1
    // Output: 0011 AND 0101 = 0001
    println!("0011 AND 0101 = {:04b}", 0b0011u32 & 0b0101);

    // Bitwise OR |: Result bit is 1 if either bit is 1
    // Output: 0011 OR 0101 = 0111
    println!("0011 OR 0101 = {:04b}", 0b0011u32 | 0b0101);

    // Bitwise XOR ^: Result bit is 1 when bits differ
    // Output: 0011 XOR 0101 = 0110
    println!("0011 XOR 0101 = {:04b}", 0b0011u32 ^ 0b0101);

    // Left Shift <<: Shift binary value left by 5 bits
    // Output: 1 shifted left 5 times = 32
    println!("1 << 5 = {}", 1u32 << 5);

    // Right Shift >>: Shift binary value right by 2 bits, {:x} outputs hexadecimal
    // Output: 0x80 shifted right 2 times = 0x20
    println!("0x80 >> 2 = 0x{:x}", 0x80u32 >> 2);

    // ========== Digit Separator _ ==========
    // Underscores only improve readability and do not change values
    // Output: One million: 1000000
    println!("One million: {}", 1_000_000u32);
}Code language: JavaScript (javascript)

3. Additional Notes on Code Execution

  1. If you change 1i32 to 1u32 and run 1u32 - 2, the code will report an error. Unsigned integers cannot represent negative numbers.
  2. {:04b}: Formatting syntax. b stands for binary, and 04 means to pad the result with leading zeros to make it 4 digits long.
  3. Use underscores to split large numbers (e.g. 1_000_000u32), it makes code much easier to read.

Previous:
Next:

Leave a Reply

Your email address will not be published. Required fields are marked *