enum
default value
programming
variables
C++

What is the default value for enum variable?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The default value of an enum variable depends on the programming language. In C and C++, an uninitialized enum variable has an indeterminate value (whatever was already in memory). In Java, an uninitialized enum field defaults to null. In C#, an uninitialized enum variable defaults to 0, which corresponds to whichever enum member has the underlying value zero. In Python, enums do not have a "default" concept because enum variables are always assigned explicitly.

This matters because relying on uninitialized default values is a common source of bugs, especially when switching between languages.

C and C++ Enum Defaults

Traditional C Enum

In C, an enum is syntactic sugar over integer constants. The first member gets value 0 by default, and each subsequent member increments by one:

c
1enum Direction {
2    NORTH,  // 0
3    EAST,   // 1
4    SOUTH,  // 2
5    WEST    // 3
6};

An uninitialized local variable of enum type has an indeterminate value. Reading it before assigning is undefined behavior:

c
1#include <stdio.h>
2
3enum Direction { NORTH, EAST, SOUTH, WEST };
4
5int main() {
6    enum Direction dir;  // Uninitialized: indeterminate value
7    printf("%d\n", dir); // Undefined behavior
8
9    enum Direction dir2 = NORTH;  // Properly initialized
10    printf("%d\n", dir2);         // 0
11    return 0;
12}

Static and global enum variables are zero-initialized, so they default to whatever member has value 0:

c
static enum Direction global_dir;  // Initialized to 0 (NORTH)

C++ Scoped Enums (enum class)

C++11 introduced scoped enums with enum class, which provide type safety and prevent implicit conversions to int:

cpp
1enum class Color {
2    Red,    // 0
3    Green,  // 1
4    Blue    // 2
5};
6
7int main() {
8    Color c{};           // Value-initialized to 0 (Color::Red)
9    Color c2;            // Uninitialized in local scope: indeterminate
10    Color c3 = Color{}; // Explicit zero-initialization: Color::Red
11
12    // Color c4 = 0;    // Compile error: no implicit conversion
13    return 0;
14}

The key difference from traditional enum is that value initialization (Color c{}) reliably gives you 0, while default initialization (Color c;) in local scope is still indeterminate.

Custom Underlying Type

Both C and C++ allow specifying starting values. If 0 is not a valid member, the "default" becomes a value that does not match any named member:

cpp
1enum class StatusCode : int {
2    OK = 200,
3    NotFound = 404,
4    ServerError = 500
5};
6
7StatusCode code{};  // Value: 0, which is none of the named members

This is a valid enum value (the underlying type is int, and 0 is a valid int), but it does not correspond to any named member. This is a common source of bugs.

Java Enum Defaults

Java enums are reference types (objects), so an uninitialized enum field defaults to null, following the same rule as all other object references:

java
1public class TrafficLight {
2    enum Signal { RED, YELLOW, GREEN }
3
4    Signal currentSignal;  // Default: null (instance field)
5
6    public static void main(String[] args) {
7        TrafficLight light = new TrafficLight();
8        System.out.println(light.currentSignal);  // null
9
10        // Accessing methods on null throws NullPointerException
11        // light.currentSignal.name();  // NPE!
12
13        // Local variables must be initialized before use
14        // Signal s;
15        // System.out.println(s);  // Compile error
16    }
17}

Important distinction: instance fields default to null, but local variables do not get a default value at all. The compiler enforces initialization of local variables.

Ordinal Values

Java enums have an ordinal() method that returns their position (starting from 0), but this is not the same as a "default value." The ordinal is just the declaration order:

java
1enum Planet {
2    MERCURY,  // ordinal 0
3    VENUS,    // ordinal 1
4    EARTH,    // ordinal 2
5    MARS      // ordinal 3
6}
7
8Planet p = Planet.values()[0];  // MERCURY (first declared member)

There is no built-in concept of a "default" member. If you want one, define it explicitly:

java
1enum Priority {
2    LOW, MEDIUM, HIGH;
3
4    public static final Priority DEFAULT = MEDIUM;
5}

C# Enum Defaults

In C#, enums are value types based on an underlying integer type (default is int). The default value is always 0, regardless of whether a member with value 0 exists:

csharp
1enum Season {
2    Spring,   // 0
3    Summer,   // 1
4    Autumn,   // 2
5    Winter    // 3
6}
7
8class Program {
9    static void Main() {
10        Season s = default;    // Season.Spring (0)
11        Season s2 = new Season();  // Season.Spring (0)
12        Console.WriteLine(s);  // Spring
13    }
14}

When No Member Has Value 0

If you assign custom values that skip 0, the default is still 0, but it does not match any named member:

csharp
1enum HttpStatus {
2    OK = 200,
3    NotFound = 404,
4    ServerError = 500
5}
6
7HttpStatus status = default;  // Value is 0, prints "0" (no named member)
8Console.WriteLine(status);    // 0
9Console.WriteLine(Enum.IsDefined(typeof(HttpStatus), status));  // False

This is why C# coding guidelines recommend always including a member with value 0 that represents "none," "unknown," or "default":

csharp
1enum HttpStatus {
2    None = 0,       // Explicit default
3    OK = 200,
4    NotFound = 404,
5    ServerError = 500
6}

Flags Enums

For [Flags] enums, the 0 value typically represents "no flags set":

csharp
1[Flags]
2enum Permissions {
3    None = 0,
4    Read = 1,
5    Write = 2,
6    Execute = 4
7}
8
9Permissions p = default;  // Permissions.None (0)

Python Enum Defaults

Python's enum module does not have a default value concept. Enum members are always accessed explicitly:

python
1from enum import Enum
2
3class Color(Enum):
4    RED = 1
5    GREEN = 2
6    BLUE = 3
7
8# No default value; must assign explicitly
9c = Color.RED
10
11# Accessing by value
12c2 = Color(1)  # Color.RED
13
14# Accessing by name
15c3 = Color['RED']  # Color.RED

If you want a default, use None as the initial value or define a class-level default:

python
1from enum import Enum
2from typing import Optional
3
4class Priority(Enum):
5    LOW = "low"
6    MEDIUM = "medium"
7    HIGH = "high"
8
9    @classmethod
10    def default(cls):
11        return cls.MEDIUM
12
13# Usage
14p: Optional[Priority] = None          # No priority set
15p2: Priority = Priority.default()     # MEDIUM

Cross-Language Comparison

LanguageUninitialized Instance FieldUninitialized Local VariableFirst Member Value
C0 (static/global), indeterminate (local)Indeterminate (undefined behavior)0
C++0 (value-init), indeterminate (default-init)Indeterminate0
JavanullCompile errorordinal 0
C#0 (first member or unnamed)Compile error0
PythonN/A (must assign)N/A (must assign)Defined by user

Best Practices

Always Define an Explicit "Unknown" or "None" Member

In languages where the default is 0, add a member that represents the unset state:

csharp
1// C#: explicit None member
2enum OrderStatus {
3    None = 0,
4    Pending = 1,
5    Shipped = 2,
6    Delivered = 3
7}

Initialize Enum Variables Explicitly

Across all languages, explicitly initializing enum variables prevents bugs from uninitialized defaults.

Common Pitfalls

Assuming C/C++ local enum variables are zero-initialized. Only static and global variables are zero-initialized. Local variables are indeterminate, and reading them is undefined behavior. Always initialize.

Forgetting that Java enum fields default to null, not the first member. This leads to NullPointerException when calling methods on uninitialized enum fields. Either initialize in the constructor or check for null.

Skipping 0 in C# enum definitions. If no member has value 0, the default is a nameless value that does not match any member. This causes confusing behavior in switch statements and serialization.

Relying on enum ordinal values for persistence. If you save Java's ordinal() or C#'s integer value to a database and later reorder the enum members, the stored values become wrong. Use explicit integer assignments or store the name string instead.

Not handling the default case in switch statements. Adding a new enum member without updating all switch statements is a silent bug. Enable compiler warnings for non-exhaustive switches, or always include a default/wildcard case that throws.

Summary

  • C/C++: local enum variables are indeterminate until initialized. Static/global default to 0.
  • Java: enum fields default to null. Local enum variables must be initialized (compiler-enforced).
  • C#: enum variables default to 0. Always include a member with value 0 to represent the "none" state.
  • Python and TypeScript: no implicit default. Variables must be assigned explicitly.
  • Best practice across all languages: initialize enum variables explicitly and define a "none" or "unknown" member for the zero/null case.
  • Never rely on ordinal position for persistence. Use explicit values or name strings.

Course illustration
Course illustration

All Rights Reserved.