1. What does this println! with numbers print?
println!("{}", 5 + 3);
println!("{}", 5 / 2);
println!("{}", 5.0 / 2.0);
println!("{}", 7 % 3);
Output:
8
2
2.5
1
5 / 2 divides two i32s → truncates to 2. 5.0 / 2.0 is float division → 2.5. 7 % 3 is 1. There’s no implicit numeric conversion in Rust — 5 / 2.0 wouldn’t even compile.
2. What does this println! with booleans print?
println!("{}", true && false);
println!("{}", true || false);
println!("{}", !true);
println!("{}", 3 > 2 && 2 > 1);
Output:
false
true
false
true
&& logical AND → false. || logical OR → true. !true → false. 3 > 2 && 2 > 1 → true. Result types are bool and print as "true"/"false".
3. What does this println! with range print?
println!("{:?}", 1..=5);
println!("{}", (1..5).len());
println!("{}", (1..=5).contains(&3));
println!("{}", (1..5).contains(&5));
Output:
1..=5
4
true
false
1..=5 prints as 1..=5 (inclusive range). (1..5).len() is 4 — the exclusive range has elements 1,2,3,4 (.len() works on exclusive ranges but not on RangeInclusive). contains(3) → true. 1..5 is exclusive of 5, so contains(5) → false. Inclusive vs exclusive ranges are a common Rust interview question.
4. What does this println! with whitespace print?
println!("{}", " hello".trim() == "hello");
println!("{}", " hello".trim_start() == "hello ");
println!("{}", " hello ".trim() == "hello");
println!("{}", " hello".trim_start() == "hello");
Output:
true
false
true
true
" hello".trim() removes both ends → "hello", matching "hello" → true. trim_start only strips the leading space, leaving "hello" which is not equal to "hello " (trailing space present) → false. " hello ".trim() → "hello" → true. " hello".trim_start() → "hello" → true. trim strips both ends; trim_start/trim_end strip only one side.
5. What does this println! with {} vs {:?} print?
let s = String::from("hi");
println!("{}", s);
println!("{:?}", s);
println!("{:?}", s.len());
Output:
hi
"hi"
2
{} uses Display → prints the string plainly hi. {:?} uses Debug → prints it quoted "hi". s.len() is 2 (byte length). The Display vs Debug formatting difference is a classic Rust gotcha.
6. What does this println! with char print?
println!("{}", 'A' as u8);
println!("{}", 'A');
println!("{}", 'A' as i32 + 1);
println!("{}", '8' as u8 - '0' as u8);
Output:
65
A
66
8
'A' as u8 converts the char to its byte value 65. 'A' prints as A through Display. 'A' as i32 + 1 is 66. '8' as u8 - '0' as u8 is 56 - 48 = 8 — the classic char-to-digit trick.
7. What does this println! with shadowing print?
let x: i32 = 10;
{
let x: &str = "twenty";
println!("inside: {}", x);
}
println!("outside: {}", x);
Output:
inside: twenty
outside: 10
The inner block shadows x with a &str of different type — Rust allows shadowing with any type. Inside, x is "twenty". Outside the block, the outer i32 x = 10 is visible again. Shadowing re-binds the name without mutating the original.
8. What does this println! with immutable vs mutable print?
let mut n = 5;
n += 1;
println!("{}", n);
let name = String::from("rust");
println!("{}", name.len());
Output:
6
4
mut allows reassignment: n becomes 6. String::len() counts bytes — "rust" is 4 bytes → 4. The second variable doesn’t need mut because it’s never reassigned.
9. What does this println! with a for loop print?
let mut sum = 0;
for i in 1..=5 {
sum += i;
}
println!("{}", sum);
Output:
15
The loop accumulates 1+2+3+4+5 = 15. 1..=5 iterates five times (inclusive). Moving sum is fine here because each iteration borrows it mutably via the +=.
10. What does this println! with division by zero print?
let a = 6;
let b = 0;
let result = a / b;
Output:
Runtime error: thread panicked, integer overflow / division by zero
Integer division by zero in Rust panics at runtime — there’s no Infinity/NaN for ints. This is deliberate: Rust’s default is panic (aborting the thread), not silent garbage, unlike C where it’s UB. Use checked_div, wrapping_div, or saturating_div to handle it.
11. What does this println! with overflow print?
let x: u8 = 255;
println!("{}", x);
let y = x + 1;
println!("{}", y);
Output:
255
Runtime error: thread panicked at 'attempt to add with overflow'
255 prints fine. Then x + 1 overflows u8. In debug builds (dev), Rust catches overflow and panics. Only in release builds does it wrap to 0 silently. This is why Rust is safer than C — overflow is caught by default.
12. What does this println! with explicit wrapping print?
let x: u8 = 255;
println!("{}", x.wrapping_add(1));
println!("{}", x.saturating_add(5));
println!("{}", (255u16 + 1) as u8);
Output:
0
255
0
wrapping_add(1) wraps to 0. saturating_add(5) saturates at 255. 255u16 + 1 is 256, then as u8 truncates to 0. These explicit operations make overflow deterministic instead of panicking.
13. What does this println! with inline math and types print?
println!("{}", 2f64.sqrt());
println!("{}", 2_i32.pow(3));
println!("{}", (2.0f64 * 3.0) as i32);
Output:
1.4142135623730951
8
6
2f64.sqrt() is the square root → 1.4142135623730951. 2_i32.pow(3) is 8. (2.0 * 3.0) as i32 — Rust allows as casts to truncate float→int → 6. as is the only “implicit-like” conversion, and it requires the explicit keyword.
14. What does this println! with a helper function print?
fn double(n: i32) -> i32 {
n * 2
}
let a = double(7);
let b = double(a);
println!("{}", b);
Output:
28
double(7) → 14. double(14) → 28. b is 28. Inside double, n * 2 is the tail expression — no return needed and no semicolon, since the last expression is the return value.
15. What does this println! with string formatting print?
let name = "Ada";
let age = 36;
println!("{} is {} years old", name, age);
println!("{:04}", 7);
println!("{:.2}", 3.14159);
Output:
Ada is 36 years old
0007
3.14
Positional placeholders {} fill in order. {:04} pads with zeros to width 4 → 0007. {:.2} rounds to 2 decimals → 3.14. Rust’s format! machinery is powerful but positional by default.
Premium Content
Unlock Output Questions - Part 1 and all premium lessons with a subscription.
From ₹199.99/year — See plans