39. Safe Callback Invocation

In embedded firmware, optional callback functions are often used to handle events such as sensor data processing.
This problem focuses on safe callback invocation using nullptr.

You are given an input that specifies whether a callback is registered and a sensor value.
Your task is to safely invoke the callback only if it is registered.

Input Format:

flag value
  • flag (integer)
    • 0 → No callback is registered
    • 1 → Callback is registered
  • value (integer)
    • Sensor data value
    • Can be positive, negative, or zero

Both values are space-separated and provided on a single line.

Output Format:

  • If flag is 0, print:
    • NO CALLBACK 
  • If flag is 1, invoke the callback and print:
    • DATA <value>
      

The output must match exactly, with no extra spaces or text.

Example 1

Input:

0 10

Output:

NO CALLBACK 

 

Example 2

Input:

1 25

Output:

DATA 25 

 

Constraints:

  • Use nullptr to represent the absence of a callback
  • Always check the callback pointer before calling it
  • value fits within a 32-bit signed integer
  • Do not invoke a null function pointer

 

 

 

 

Need Help? Refer to the Quick Guide below

In C, the macro NULL is typically defined as ((void*)0) or simply integer 0.

In C++, this integer definition causes dangerous ambiguity because 0 is both an integer and a pointer.

nullptr (introduced in C++11) is a specific keyword that represents a null pointer literal. It is strictly a pointer type, not an integer. It implicitly converts to any pointer type (int*, char*, MyClass*) but never to an integer.

Syntax & Usage

1. Basic Assignment

// C-Style (Ambiguous)
int *p1 = NULL;    // Actually int *p1 = 0;

// C++ Style (Safe)
int *p2 = nullptr; // Explicitly a null pointer type

2. Boolean Checks

nullptr behaves like a boolean false in conditionals, just like NULL.

if (ptr == nullptr) {
    // Handle error
}
if (!ptr) {
    // Also works
}

Why NULL is Dangerous (The Overloading Trap)

This is the primary reason nullptr exists. When you have overloaded functions, NULL behaves like the integer 0, often calling the wrong function.

void log(int code) {
    // Logs an error code
}

void log(char *msg) {
    // Logs a string message
}

// CALLING:
log(NULL);    // ❌ AMBIGUITY! Calls log(int) because NULL is 0.
log(nullptr); // ✅ CORRECT. Calls log(char*) because nullptr is a pointer.

Relevance in Embedded/Firmware

1. Safer Hardware Abstraction Layers (HAL)

Embedded APIs often overload functions for convenience.

  • write(uint8_t value) for writing a single byte.
  • write(uint8_t *buffer) for writing an array. Using nullptr ensures you don't accidentally write a "0" byte when you meant to signal an empty buffer.

2. Template Metaprogramming

When writing generic drivers (Templates), passing 0 (integer) where a pointer type is deduced can cause cryptic template instantiation errors. nullptr allows the compiler to deduce the type correctly as "some pointer."

3. Code Readability

nullptr makes it explicit: "This variable is a pointer pointing to nothing."

0 or NULL could mean "Integer Zero" or "ASCII Null" or "Pointer Null."

Common Pitfalls (Practical Tips)

PitfallDetails
❌ Using nullptr with integersint x = nullptr; is a compile-time error. This is a good thing—it catches logic bugs where you assign pointers to counters variables.
❌ Legacy Code

Old C++98 codebases (or very old compilers) do not support nullptr.

Fix: Most modern embedded compilers (GCC ARM, IAR) support C++11/14/17 standard by default. Ensure your compiler flag is set (e.g., -std=c++11).

✅ Global ReplacementsIt is generally safe and recommended to find-and-replace NULL with nullptr in all C++ source files, provided you are not passing it to a function explicitly expecting an integer (which would be a bug anyway).