Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

📝 Knowledge Test

/
Knowledge Test Score Board
· 0%

Work through the questions below — your score updates as you go.

Keep going · grade bands mapped to DCU's honours scale

target15:00

Only your first attempt at each question counts toward this score. Reload the page to reset.

This section contains 20 interactive knowledge checks designed to test your understanding of the materials covered in Chapter 7. The questions cover Rust’s ecosystem, memory management, ownership, borrowing, and custom data types.

Please remember that many of the quizzes have multiple correct answers, and you must select all applicable options to succeed. I have carefully balanced the lengths of the answers, so take your time to evaluate each option thoroughly.

Good luck!

Derek.


Q1
Concept Match

Match Rust Core Advantages

Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.

no_std
drag a definition here…
embedded-hal
drag a definition here…
serde
drag a definition here…
Cargo
drag a definition here…

Definition Pool

A framework for serialising data with zero runtime overhead via compile-time generation.
Enables Rust to run on bare-metal hardware without an operating system.
Provides a set of traits allowing drivers to be portable across different microcontrollers.
A unified toolchain for building, testing, and managing dependencies securely.
Q2
Quiz
Select 0/1

Which of the following statements correctly describes the role of the Cargo.lock file in a professional Rust project?

It provides a temporary caching mechanism for the compiler to significantly speed up the linking phase.
It ensures reproducible builds by rigorously recording the exact versions of all dependencies used.
It securely stores the project's metadata and manually defined list of required external dependencies.
It configures the user's personal preferences for the rust-analyzer extension within the VS Code editor.
Q3
Quiz
Select 0/1

Why is Rust considered to have a distinct advantage over C/C++ regarding memory safety in edge programming?

It forces developers to allocate all complex data structures exclusively on the stack for guaranteed safety.
It utilises a highly optimised runtime garbage collector to automatically reclaim unused memory chunks.
It dynamically checks all pointer arithmetic operations during program execution to prevent overflows.
It enforces strict ownership rules at compile time, eliminating common bugs like use-after-free.
Q4
Code Cloze

Cargo Build and Check Commands

Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.

1# Verify that code is syntactically and semantically correct without generating a binary:
2cargo ·····
3
4# To compile the project and its dependencies into an executable binary, use:
5cargo ·····

Available Snippets

compile
verify
test
run
build
check
Q5
Concept Match

Match Ownership and Memory Concepts

Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.

Move Semantics
drag a definition here…
Copy Trait
drag a definition here…
Clone Trait
drag a definition here…
Shadowing
drag a definition here…

Definition Pool

An implicit bitwise duplication for simple types that preserves the source variable.
Re-using a variable name by creating a new binding, potentially altering its underlying type.
The default behaviour where ownership is transferred, invalidating the original variable.
An explicit mechanism for performing a deep copy of heap-allocated data structures.
Q6
Code Output
Rust

Predict the output: Shadowing and Scopes

Read the code below, then choose the terminal output it produces and click Submit.

1fn main() {
2 let x = 5;
3 let x = x + 1;
4 {
5 let x = x * 2;
6 print!("{} ", x);
7 }
8 print!("{}", x);
9}
stdout
12 6
stdout
12 12
stdout
6 6
stdout
10 5
Q7
Quiz
Select 0/1

In the context of Rust's memory layout, which of the following statements accurately describes the String type?

It allocates all of its character data directly on the stack to guarantee fast, deterministic access.
It is a 24-byte fat pointer on the stack containing a pointer, length, and capacity, with data on the heap.
It stores UTF-32 encoded characters contiguously on the heap, matching the standard behaviour of C++ strings.
It operates as a thin pointer on the stack that automatically grows its allocation during compilation.
Q8
Code Cloze
Rust

Memory Layout of Box

Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.

1fn main() {
2 // A Box<i32> is an owning pointer to data on the heap.
3 let b: Box<i32> = Box::·····(42);
4 // The pointer itself takes up ····· bytes on a 64-bit machine's stack.
5}

Available Snippets

new
alloc
24
4
8
make
Q9
Quiz
Select 0/1

How do Rust's strict borrowing rules directly prevent data races in concurrent programming?

By transparently copying the underlying data to each thread so they all possess their own local versions.
By requiring developers to manually implement mutexes and locks around every complex data structure.
By enforcing that exactly one mutable reference, or multiple immutable references, exist at any given time.
By automatically pausing all background threads whenever a shared variable is accessed by the main thread.
Q10
Code Cloze
Rust

Safe Mutable References

Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.

1// The function signature requires a mutable reference
2fn modify_text(s: ····· String) {
3 s.push_str(" world");
4}
5
6fn main() {
7 // The variable must be declared as mutable to be mutably borrowed
8 let ····· text = String::from("hello");
9 // Pass a mutable reference to the function
10 modify_text(····· text);
11}

Available Snippets

&mut
*mut
&mut
const
ref
&
mut
Q11
Quiz
Select 0/1

What is the primary purpose of lifetimes in Rust's type system?

They ensure that all variables remain active in memory until the main function completes its execution.
They act as a compile-time proof that references will not outlive the underlying data they point to.
They provide a runtime mechanism for the garbage collector to determine when to free allocated memory.
They automatically extend the scope of a stack-allocated variable to prevent it from being dropped.
Q12
Concept Match

Match Slices and References

Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.

Slice (&[T])
drag a definition here…
String Slice (&str)
drag a definition here…
Dangling Reference
drag a definition here…
Lifetime Elision
drag a definition here…

Definition Pool

A non-owning reference to a contiguous sequence of elements within a collection.
A specialised view for UTF-8 data, functioning as a two-word fat pointer.
A pointer to memory that has already been deallocated or gone out of scope.
Compiler rules that automatically infer references' valid scopes to reduce verbosity.

Part 4: Language Fundamentals & Control Flow

Section titled “Part 4: Language Fundamentals & Control Flow”
Q13
Code Order
Rust

Implicit Returns and Statements

Drag the tiles to arrange the code in the correct order, then click Submit. Locked lines stay in place. Indentation is dynamically applied based on the location of braces.
fn add_and_check(a: i32, b: i32) -> i32 {
}
sum
return 10;
let sum = a + b;
if sum > 10 {
}
Q14
Code Cloze
Rust

Returning from a loop

Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.

1fn main() {
2 let mut counter = 0;
3 let result = loop {
4 counter += 1;
5 if counter == 5 {
6 // Halt the loop and return the calculated value
7 ····· counter * 2;
8 }
9 };
10 println!("Result: {}", result);
11}

Available Snippets

break
return
yield
continue
exit
Q15
Quiz
Select 0/1

Why is Rust's match expression generally considered safer and more robust than a traditional C++ switch statement?

It automatically converts string inputs into their corresponding integer values prior to evaluation.
It entirely prevents the use of integer types, forcing developers to rely exclusively on enumerated types.
It enforces exhaustiveness at compile time, guaranteeing that every possible variant or case is handled.
It dynamically generates fallback branches at runtime to handle unexpected or malformed data inputs.
Q16
Quiz
Select 0/1

Which of the following accurately contrasts Rust macros with the C++ preprocessor (#define)?

Rust macros are restricted exclusively to standard library functions and cannot be defined by application developers.
Rust macros execute entirely at runtime, allowing them to dynamically generate code based on user inputs.
Rust macros operate on the Abstract Syntax Tree (AST) and enforce hygiene, preventing accidental name collisions.
Rust macros perform simple textual substitution before compilation, exactly matching the behaviour of the C++ preprocessor.
Q17
Concept Match

Match Custom Types and Implementations

Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.

Unit Struct
drag a definition here…
Tuple Struct
drag a definition here…
Classic Struct
drag a definition here…
Associated Function
drag a definition here…

Definition Pool

A composite type with named fields, analogous to a standard C++ class or struct.
Defined within an impl block without a self parameter, often functioning as a constructor.
A named collection of unnamed fields that are accessed primarily by their numeric index.
A field-less struct primarily used as a marker type to distinguish different states.
Q18
Code Cloze
Rust

Enum Destructuring

Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.

1enum Command {
2 Move(f64),
3 TurnLeft,
4}
5
6fn execute(cmd: Command) {
7 match cmd {
8 // Destructure the f64 data into the distance variable
9 Command::Move(·····) => println!("Moving {}", distance),
10 Command::TurnLeft => println!("Turning"),
11 }
12}

Available Snippets

f64
_
distance
val
value
Q19
Quiz
Select 0/1

In the context of edge programming, what is the primary advantage of Rust's default use of static dispatch (monomorphisation)?

It enables maximum runtime flexibility, allowing types to be dynamically swapped during execution.
It drastically minimises the size of the final compiled binary by sharing code across all generic types.
It completely eliminates compilation time overhead by delaying type resolution until the program runs.
It allows the compiler to generate highly optimised, type-specific machine code with zero runtime overhead.
Q20
Quiz
Select 0/1

Since Rust does not support traditional class-based inheritance, how does it typically achieve abstraction and polymorphism?

By relying entirely on procedural macros to generate necessary boilerplate code for inherited classes.
By employing smart pointers to dynamically link objects together into a hierarchical memory structure.
By utilising complex C-style unions combined with bitwise operators to emulate object hierarchies.
By defining data structures with structs and specifying shared behaviours and interfaces through traits.

Congratulations on completing the Chapter 7 Knowledge Test! Review any questions you missed to ensure a solid grasp of Rust’s ownership model, borrowing rules, and custom data types before proceeding.