Introduction: Why Naming is the “First Button” of Coding

Hello engineers and fellow developers at www.123microcontroller.com! Today, the dark-eyed engineer is here to discuss a topic that might seem like a mere matter of style or aesthetics. In reality, it is the “first button” of writing bug-free, safe embedded code: Naming Conventions.

In hardware-level programming, naming is just like labeling electrical wires in a control cabinet. If labeled correctly, your code is highly readable, instantly understandable, and prevents miswiring! In the context of Writing Safer C, utilizing Snake case or appending Prefixes isn’t just about personal preference; it’s an “engineering strategy” used by C masters to mitigate the language’s weaknesses and avoid dreaded name collisions. Let’s delve into the reasoning behind these rules!

Why Does Naming Make Code Safer?

C is phenomenally powerful but inherently raw. One of its main drawbacks is the lack of a proper Namespace system, unlike C++. Consequently, all global variables and functions are dumped into a single, global scope, creating chaos and a high risk for name collisions.

To impose structural order (Writing Safer C), global references and standards like BARR-C recommend specific naming techniques to aggressively control these risks:

  • Snake Case—Powerful and Traditional: In the C ecosystem, using all lowercase letters separated by underscores—known as Snake case (e.g., list_count or hours_worked)—is an almost universal standard for naming variables and functions. While some developer factions prefer Camel case (e.g., currentPage), the golden rule is maximizing readability and distinctiveness to reduce human errors.
  • Prefixes to Simulate Namespaces and Encapsulation: Since C lacks native namespaces, we rely on Prefixes to organize our codebase!
    • Module Prefixes: The BARR-C standard strongly advises prefixing public functions with their parent module’s name (e.g., sensor_read()). This effectively eradicates naming collisions across the system and immediately signals what data/noun this function is operating heavily upon.
    • Struct/Type Prefixes: For functions strictly operating on a specific Struct, the Struct’s name typically serves as the prefix (e.g., list_is_empty(struct list* lst)).
    • Struct Member Prefixes: Historically, older C compilers utilized a single global symbol table. Prefixing Struct members prevented severe collisions. Even today, prefixing members acts as a safeguard against naming conflicts with careless Macros defined in obscure header files by other developers (e.g., the standard struct timespec uses the member tv_sec rather than just sec).
  • Screaming Snake Case for Macros and Constants: To violently segregate program variables from Preprocessor directives, the standard rule is straightforward: strictly use entirely uppercase letters separated by underscores (e.g., MAX_BUFFER_SIZE) for Macros and constants. This immediately alerts someone reading the code that this identifier is handled purely by the preprocessor and should never be misused as a standard variable.

Naming Conventions Diagram

Code Example: Applying Naming Conventions in Practice

Let’s review an embedded sensor code snippet demonstrating how Naming Conventions are applied for engineering safety.

#include <stdint.h>
#include <stdbool.h>

/* ✅ BEST PRACTICE: Use Screaming Snake Case for Constants and Macros */
#define SENSOR_MAX_RETRY_COUNT (5U)

/* 
 * ✅ BEST PRACTICE: Use Snake case with highly descriptive nouns
 * (Use sensor_data instead of cryptic acronyms like sd)
 */
typedef struct {
    uint32_t raw_value;
    bool     is_active;
} sensor_data_t;

/* 
 * ✅ BEST PRACTICE: Utilize Module Prefixes ('sensor_') for Public functions
 * to prevent Name collisions with the read/init functions of rival modules.
 * Also, end with a Verb describing the exact action.
 */
bool sensor_init(sensor_data_t *sensor) {
    if (sensor == NULL) {
        return false;
    }
    
    // ✅ Internal variables use descriptive Snake case
    uint8_t retry_count = 0; 
    
    while (retry_count < SENSOR_MAX_RETRY_COUNT) {
        /* Simulating hardware reset operations */
        sensor->raw_value = 0;
        sensor->is_active = true;
        retry_count++;
        break;
    }
    return sensor->is_active;
}

Naming Pitfalls Every Hardcore Engineer Must Know

Beyond readability, the ISO C standard and Secure Coding guidelines have strict “forbidden” rules you must memorize to prevent Undefined Behaviors:

  1. Never Steal Reserved Identifiers: You are strictly forbidden from naming an Identifier starting with two consecutive underscores (__) or a single underscore followed directly by an Uppercase letter (e.g., _Variable). These are rigorously “reserved” for compilers and future C Standards. Trespassing here can invisibly break your firmware without throwing immediate errors.
  2. Use Highly Descriptive Names: Never fear long variable names! Modern C compilers have effectively no practical length limits. Therefore, explicitly use current_page rather than ambiguous abbreviations like cp, which drastically hurt long-term maintainability.
  3. Naming Handles (BARR-C Rule): If following BARR-C, any variable acting as a non-pointer “Handle” to an object (such as file handles) should be prefixed with h_ (e.g., h_input_file). This provides immediate, unmistakable context regarding the resource type being manipulated.
  4. Consistency is the Ultimate Rule: Regardless of whether your team elects Snake case, Camel case, or a bizarre hybrid, you must “choose and stick to it universally across the project”. Haphazard styles scattered throughout (like makegreen(), makeGreen(), and makeGREEN()) invite catastrophic developer confusion and inject rapid bugs.

Conclusion

To evolve into a senior engineer capable of executing Safer C, realizing that Naming Conventions are not personal aesthetics is pivotal. They are “tools” engineered to tame the wild rawness of C. Deploying Snake case and Prefixes constructs rigid boundaries for your variables, obliterates name collisions, and allows subsequent developers reading your code to digest your hardware logic instantly—as if reviewing a pristine, high-grade architectural blueprint.

If you enjoy these deep discussions bridging computer science theory and industrial standards, be sure to keep following, chatting, and sharing awesome code at www.123microcontroller.com. Great software genuinely starts with proper names! See you in the next article. Happy Coding!