9.2 Data Types, Variables & Identifiers

Key Takeaways

  • Identifiers serve as human-readable labels for variables, constants, and subroutines; they must conform to language syntax rules (alphanumeric and underscores, never starting with a digit, no reserved keywords) and standard conventions (camelCase, PascalCase, snake_case, UPPER_SNAKE_CASE).
  • Variables represent mutable memory locations whose stored values can be updated throughout program execution, whereas constants represent immutable storage locations locked upon initialization to prevent accidental logic corruption.
  • Primitive data types define memory allocation footprints and permissible operations: Integers (signed vs unsigned whole numbers), Floating-Point numbers (IEEE 754 single and double precision decimals), Characters (single ASCII/Unicode symbols), Strings (ordered character sequences), and Booleans (logical truth values).
  • Typing systems determine how strictly variable types are enforced: Statically typed languages verify types at compile time to catch mismatches early, whereas Dynamically typed languages evaluate types at runtime to maximize prototyping flexibility.
  • Type casting transforms values between types: Implicit type coercion occurs automatically when widening without data loss, while Explicit type casting intentionally forces conversions, introducing risks of decimal truncation, precision loss, and integer overflow.
Last updated: September 2026

Data Types, Variables & Identifiers

Core Foundation: Every software application is fundamentally an information processing engine that manipulates data stored within computer memory. To manage this data reliably, programming languages provide structural abstractions: identifiers to label memory locations, variables and constants to manage mutability, primitive data types to define memory bit depths, and typing disciplines to enforce operational validity.


Identifiers: Syntax Rules vs. Naming Conventions

An identifier is a developer-defined textual token used to name a programming entity, such as a variable, constant, function, procedure, class, or data structure. Compilers and interpreters enforce rigid syntactic rules regarding identifiers, while software engineering organizations establish naming conventions to maintain codebase readability.

1. Mandatory Identifier Syntax Rules

If an identifier violates a language's syntax rules, the compiler or interpreter rejects the code with a syntax error:

  1. Permitted Characters: Identifiers may contain alphanumeric characters (uppercase letters A–Z, lowercase letters a–z, and digits 0–9) and the underscore character (_). In some languages, characters like $ are permitted for specific internal frameworks.
  2. Cannot Begin with a Digit: An identifier must never begin with a numeric digit. For example, userCount2 and _tempValue are valid, but 2ndUser or 9lives are illegal syntax errors. This rule allows the compiler's lexical scanner to differentiate numeric literal values from variable names immediately.
  3. Prohibition of Whitespace and Special Characters: Identifiers cannot contain spaces, hyphens, or punctuation marks (such as -, ., @, !, #, ?). A name like user-name is parsed as subtraction (user minus name), not a single identifier.
  4. Reserved Keywords are Forbidden: Identifiers cannot match the language's reserved keywords—words set aside by the language specification to define language grammar (e.g., if, else, while, for, class, return, int, true, false, switch).
  5. Case Sensitivity: In virtually all modern high-level languages (C, C++, Java, C#, Python, JavaScript), identifiers are strictly case-sensitive. The identifiers totalSales, TotalSales, and TOTALSALES refer to three entirely separate memory locations.

2. Standard Identifier Naming Conventions

While compilers allow any identifier that satisfies the syntax rules, professional developers follow established casing conventions to signal the role and scope of an entity:

  • camelCase (Lower Camel Case): The initial word begins with a lowercase letter, and the first letter of each subsequent concatenated word is capitalized without spaces. Standard for variable names, object properties, and function/method names in JavaScript, Java, C#, and TypeScript.
    • Examples: accountBalance, calculateTotalTax(), isCustomerVerified
  • PascalCase (Upper Camel Case): Every concatenated word begins with a capital letter, including the first word. Standard for class names, interfaces, custom data types, and C# method names.
    • Examples: CustomerAccount, PaymentGateway, InventoryRecord
  • snake_case: All letters are written in lowercase, with concatenated words separated by an underscore (_). Standard for variable names, function names, and module filenames in Python, C, Ruby, and relational database table/column definitions.
    • Examples: user_account_id, calculate_shipping_rate(), order_status
  • UPPER_SNAKE_CASE (Screaming Snake Case): All letters are written in uppercase, with words separated by underscores. Standard across almost all programming languages to designate constants (immutable values).
    • Examples: MAX_RETRY_ATTEMPTS, PI, DEFAULT_TIMEOUT_MS, SALES_TAX_RATE
Naming ConventionCapitalization PatternTypical Target EntityConcrete Code Example
camelCaseFirst word lower, subsequent words capitalizedVariables, functions, object propertieslet employeeHourlyRate = 28.50;
PascalCaseEvery word capitalizedClasses, structs, interfaces, data typesclass OrderProcessor { ... }
snake_caseAll lowercase words separated by underscoresPython/C variables, database column namesuser_session_token = "xyz123"
UPPER_SNAKE_CASEAll uppercase words separated by underscoresImmutable constants, global environment flagsconst MAX_DB_CONNECTIONS = 100;

Variables vs. Constants: Storage and Mutability

When a program executes, data is held in physical volatile memory (RAM). Variables and constants provide named abstractions over physical memory addresses.

Physical RAM Address: 0x7FFEED4B   --> Value: 42   <-- Identifier: currentScore (Variable: Mutable)
Physical RAM Address: 0x7FFEED50   --> Value: 3.14 <-- Identifier: PI           (Constant: Immutable)

1. Variables: Mutable Working Storage

A variable is a named storage location in memory whose assigned value can be changed, overwritten, or modified during program execution.

  • When a variable is initialized, the operating system allocates a block of memory corresponding to the variable's data type.
  • During execution, arithmetic operations, user input, or iterative loops can overwrite the data residing at that memory address.
  • Example: A variable itemsInCart starts at 0, increments to 1 when the user clicks "Add to Cart", and increments to 3 as shopping continues.

2. Constants: Immutable Guardrails

A constant is a named storage location in memory whose value is locked upon initialization and cannot be altered or reassigned during program execution.

  • Languages enforce immutability through explicit keywords (such as const in JavaScript, C, and C++; final in Java; or val in Kotlin).
  • If an instruction attempts to reassign a value to an established constant (e.g., attempting MAX_USERS = 500; after declaring const MAX_USERS = 250;), the compiler or interpreter throws an immediate fatal error.
  • Engineering Benefits of Constants:
    • Prevents Accidental Logic Bugs: Guards critical configuration parameters, financial multipliers, and physical constants from being overwritten by rogue loops or errant functions.
    • Eliminates "Magic Numbers": Replaces arbitrary numeric literals scattered throughout code with meaningful, centrally defined labels (e.g., using MAX_LOGIN_ATTEMPTS instead of repeatedly hardcoding the raw number 3).
    • Compiler Optimization: Because the value never changes, compilers can replace constant references with direct literal values inside the machine instructions (inlining), boosting CPU execution speed.

Primitive Data Types and Memory Footprints

A data type defines the classification of data that a variable can hold. It instructs the compiler or interpreter on two critical parameters: how many bits of memory to allocate and what mathematical or logical operations are permissible on that data.

+--------------------------------------------------------------------------+
|                       PRIMITIVE DATA TYPE TAXONOMY                       |
|                                                                          |
|   +-------------------+    +--------------------+    +---------------+   |
|   |     NUMERIC       |    |     TEXTUAL        |    |    LOGICAL    |   |
|   +-------------------+    +--------------------+    +---------------+   |
|     │               │        │                │        │                 |
|     ▼               ▼        ▼                ▼        ▼                 |
|  [Integers]     [Floats]  [Character]      [String]  [Boolean]           |
|  (Whole #)     (Decimals) (Single Glyph)   (Text)    (true/false)        |
+--------------------------------------------------------------------------+

1. Integers (Whole Numbers)

Integers represent positive whole numbers, negative whole numbers, and zero, with no fractional or decimal components.

  • Signed vs. Unsigned Integers:
    • Signed Integers: Can represent both positive and negative values. The system utilizes Two's Complement binary encoding, reserving the Most Significant Bit (MSB, the leftmost bit) as a sign bit (0 for positive, 1 for negative).
    • Unsigned Integers: Can represent only zero and positive values. Because no bit is reserved for a sign flag, the maximum positive value is doubled compared to a signed integer of the identical bit depth.
  • Standard Bit Depths and Ranges:
    • 8-bit Byte: Signed: $-128$ to $+127$. Unsigned: $0$ to $255$.
    • 16-bit Short: Signed: $-32,768$ to $+32,767$. Unsigned: $0$ to $65,535$.
    • 32-bit Integer (int): The standard integer size on modern architectures. Signed: $-2,147,483,648$ to $+2,147,483,647$ (approximately $\pm 2.14$ billion). Unsigned: $0$ to $4,294,967,295$ (approximately $4.29$ billion).
    • 64-bit Long / BigInt: Signed: approximately $-9.22 \times 10^{18}$ to $+9.22 \times 10^{18}$ (quintillions). Used for enterprise financial ledgers, epoch microsecond timestamps, and massive database foreign keys.

2. Floating-Point Numbers (Decimals / Real Numbers)

Floating-point numbers represent real numbers that contain fractional decimal components or require scientific exponential notation (e.g., $3.14159$, $-0.0075$, $6.022 \times 10^{23}$).

  • IEEE 754 Standard: Modern microprocessors implement the IEEE 754 standard for floating-point arithmetic. A floating-point number is partitioned into three binary components: a sign bit, an exponent, and a mantissa (fraction/significand).
  • Single-Precision Float (32-bit): Allocates 1 sign bit, 8 exponent bits, and 23 mantissa bits. Provides approximately 7 decimal digits of precision.
  • Double-Precision Float (64-bit / double): Allocates 1 sign bit, 11 exponent bits, and 52 mantissa bits. Provides approximately 15 to 17 decimal digits of precision. Double precision is the default numeric decimal type in Java, C++, Python, and JavaScript.
  • The Floating-Point Inexactness Hazard: Binary floating-point cannot precisely represent certain base-10 fractions (such as $0.1$ or $0.2$), leading to micro-rounding discrepancies (e.g., evaluating $0.1 + 0.2$ in Python or JavaScript yields $0.30000000000000004$). For currency transactions and banking calculations, developers must never use standard floats; they use dedicated Fixed-Point or arbitrary-precision Decimal types (such as Java's BigDecimal or Python's decimal.Decimal).

3. Characters (char)

A character represents a single alphanumeric glyph, typographic symbol, punctuation mark, or system control code.

  • In code syntax, character literals are conventionally enclosed in single quotation marks (e.g., 'A', '7', '$', ' ').
  • ASCII Representation: Legacy 7-bit and 8-bit ASCII maps characters to numeric values from $0$ to $255$ (1 byte).
  • Unicode Representation: Modern systems store characters using 16-bit code units (UTF-16) or variable 1-to-4 byte encodings (UTF-8), accommodating international alphabets, Asian ideographs, and emojis.

4. Strings

A string is an ordered sequence of characters treated as a unified data structure. In code syntax, strings are conventionally enclosed in double quotation marks (e.g., "CompTIA Tech+" or "user@example.com").

  • Zero-Indexed Access: Individual characters within a string are accessed via a zero-based index. For string text = "TECH", text[0] is 'T', text[1] is 'E', text[2] is 'C', and text[3] is 'H'.
  • Concatenation: Combining two or more strings together sequentially using the concatenation operator (+). For example, "Cyber" + "Security" evaluates to "CyberSecurity".
  • String Immutability: In many prominent high-level languages (including Python, Java, and C#), strings are immutable. When a string variable appears to be modified (e.g., converted to uppercase), the runtime does not alter the original memory buffer; it allocates an entirely new string object in memory.

5. Booleans (bool / boolean)

A Boolean represents a binary logical truth value: either true or false (conceptually 1 or 0).

  • Booleans are named after English mathematician George Boole, who formulated Boolean algebra.
  • Memory Storage Reality: Mathematically, a boolean requires only 1 single bit of information. However, because modern computer CPUs are built on byte-addressable memory architectures (memory addresses point to 8-bit bytes, not individual bits), most runtimes allocate an entire 8-bit byte to store a single boolean variable.
  • Booleans serve as conditional flags that dictate control flow execution in branching statements (if) and loops (while).
Primitive Data TypeTypical KeywordsMemory FootprintRepresentable Value Range / PrecisionConcrete Literal Example
Integerint, long, short16, 32, or 64 bitsSigned 32-bit: $-2.14\text{B}$ to $+2.14\text{B}$int userAge = 24;
Floating-Pointfloat, double32 bits (single) / 64 bits (double)64-bit double: $\sim 15\text{--}17$ decimal digitsdouble fuelPrice = 3.899;
Characterchar8 bits (ASCII) / 16 bits (Unicode)Single alphanumeric or punctuation symbolchar grade = 'A';
Stringstring, StringVariable (1 byte per ASCII char + overhead)Sequence of zero or more charactersstring name = "Jordan";
Booleanbool, boolean8 bits (1 byte addressable storage)Strictly binary truth states: true or falsebool isAuthenticated = false;

Typing Systems: Statically Typed vs. Dynamically Typed

Programming languages enforce type safety through distinct typing disciplines that dictate when variable data types are established and validated.

1. Statically Typed Languages

In a statically typed language, variable data types are explicitly declared by the programmer (or statically inferred by the compiler) at the time of code creation, and are permanently locked during compilation.

  • Compile-Time Verification: The compiler verifies type compatibility before generating machine binaries. If a developer attempts to assign a text string to an integer variable (e.g., int count = "five";), compilation halts with a fatal type error.
  • Representative Languages: C, C++, Java, Rust, Go, C#, and TypeScript.
  • Advantages: Catches data mismatch bugs early in development before code reaches users; allows compilers to generate highly optimized, high-speed machine instructions; self-documenting code.
  • Disadvantages: More verbose source code; requires explicit casting and longer initial development cycles.

2. Dynamically Typed Languages

In a dynamically typed language, variable types are not declared in source code. Types are bound to the underlying runtime values, not to the variable container itself.

  • Runtime Evaluation: A variable can hold an integer, and later in the same execution thread be reassigned a string or a list. The interpreter tracks and verifies types dynamically as each statement executes.
  • Representative Languages: Python, JavaScript, Ruby, and PHP.
  • Advantages: Rapid prototyping; concise, flexible code syntax; lower barrier to entry for junior engineers.
  • Disadvantages: Slower runtime execution due to continuous dynamic type checking; risk of runtime type crashes (such as TypeError or JavaScript NaN values) occurring in production environments.

Type Casting: Implicit Coercion vs. Explicit Conversion

During software execution, programs frequently need to convert data from one data type to another. This process is known as type casting or type conversion.

Implicit Type Coercion (Widening - Safe):   [int: 42]  ───────> [double: 42.0]  (Zero Data Loss)
Explicit Type Casting (Narrowing - Lossy): [double: 9.87] ───> [int: 9]        (Fraction Truncated!)

1. Implicit Type Coercion (Automatic / Widening Conversion)

Implicit type conversion occurs automatically behind the scenes when the compiler or runtime converts a narrower data type into a wider data type without requiring programmer intervention.

  • Widening Conversion (Safe): When an operation combines an integer and a floating-point number, the runtime automatically promotes the integer to a float because no mathematical precision is lost.
  • Example: In Java or C++, evaluating double total = 10 + 2.5; causes the integer 10 to implicitly convert to 10.0, producing float 12.5.
  • The JavaScript Coercion Trap: In loosely typed dynamic environments like JavaScript, implicit coercion can produce unexpected bugs. Evaluating "5" + 2 treats + as string concatenation, yielding the string "52". Conversely, evaluating "5" - 2 coerces the string to a number, yielding the integer 3.

2. Explicit Type Casting (Manual / Narrowing Conversion)

Explicit type casting occurs when the programmer deliberately commands the system to transform a value into a target data type using explicit casting syntax or conversion functions.

  • Narrowing Conversion (Lossy): Converting a wider data type into a narrower data type (such as forcing a 64-bit float into a 32-bit integer).
  • Syntax Examples:
    • In C/Java: int truncatedValue = (int) 9.87; (yields 9)
    • In Python: integer_count = int("42")
    • In JavaScript: let numericScore = parseInt("100");

3. Critical Risks of Type Casting

  • Truncation of Fractional Data: When a floating-point value is cast to an integer, the fractional decimal component is truncated (discarded entirely)—it is NOT mathematically rounded. Casting 9.99 to an integer results in 9, permanently losing the decimal precision.
  • Integer Overflow and Underflow: If a 32-bit integer with a large value is cast into an 8-bit byte (which can only hold values up to $255$), the high-order bits are sliced off. Casting decimal 300 into an 8-bit unsigned byte causes the value to wrap around modulo 256, storing the unexpected value 44 ($300 - 256 = 44$).
  • Parsing Exceptions: If a program attempts to parse non-numeric string data into an integer (e.g., executing int("twenty")), the runtime will throw an unhandled parsing exception (ValueError or NumberFormatException), crashing the application if unhandled.
Loading diagram...
Hierarchy of Fundamental Programming Data Types and Memory Footprints
Test Your Knowledge

A developer is writing code to calculate commercial freight costs. A fixed fuel surcharge multiplier of 1.15 must be referenced throughout hundreds of shipping calculation routines, but its value must be permanently protected against accidental modification during execution. According to industry best practices, how should this identifier be configured?

A
B
C
D
Test Your Knowledge

In common languages that use C-style identifier rules, which name begins with an illegal character and would cause a syntax error?

A
B
C
D
Test Your Knowledge

In a C-style statically typed language, a routine executes the narrowing cast int convertedVal = (int) 15.92;. What value is stored, and what happened?

A
B
C
D
Test Your Knowledge

Which primitive data type is specifically engineered to hold a single logical truth value representing exclusively either true or false?

A
B
C
D