← Core SyntaxC PROGRAMMING 1.1.B

Variables & Data Types

Declaration vs initialization, integer types, unsigned wraparound, floats, sizeof, fixed-width types, overflow, conversion, const, scope.

StatusCollected
NotesChapter test: 4/4

This chapter is basically "how big is a number and what happens when it's too big." Ten pieces: declaration vs initialization, the integer type ladder, unsigned, floats, sizeof, fixed-width types, overflow, conversion, constants, and scope.

Declaration vs initialization

int x; and int x = 0; are not the same thing. The first reserves space and leaves whatever garbage was already sitting in that memory; the second actually puts a value there. Reading an uninitialized local is undefined behavior — it might print 0 by luck on one run and something else the next.

The integer type ladder

TypeTypical sizeNotes
char1 bytesignedness is implementation-defined
short2 bytes
int4 bytesthe default choice, but never a guaranteed size
long4 or 8 bytes8 on most 64-bit Linux, 4 on Windows
long long8 bytesguaranteed at least 64 bits
#include <stdio.h>

int main(void) {
    printf("%zu\n", sizeof(int));
    printf("%zu\n", sizeof(long));
    return 0;
}

sizeof resolves at compile time, not runtime — which is why it's legal to use it in an array-size declaration.

unsigned and wraparound

unsigned shifts the whole range up instead of splitting it across negative and positive — an unsigned int on a 4-byte system runs 0 to 4294967295 instead of roughly ±2 billion. Subtracting past zero doesn't error, it wraps around to the top of that range:

unsigned int u = 0;
u = u - 1;          // wraps to UINT_MAX (4294967295), not -1

Fixed-width types

uint8_t, uint16_t, uint32_t, uint64_t (from <stdint.h>) say exactly what they mean — int never promises a specific width, but uint32_t is always 32 bits on any platform. That's the whole reason they exist: register maps and wire protocols need a guaranteed size, not whatever the compiler feels like giving int.

Constants and scope

  • const int x = 5; — a typed, scoped constant the compiler can actually check.
  • #define X 5 — a preprocessor text substitution, with no type and no scope; it's gone before the compiler even sees real C.
  • Local scope — exists only inside the block it's declared in.
  • Global scope — file-level, visible everywhere unless marked static.
  • Block scope — even inside an if or a loop body, a variable declared there dies at the closing brace.

Notes from readers

Comments — via GitHub