Menu
Coddy logo textTech

The First Member Rule

Part of the Object Oriented Programming section of Coddy's C journey — lesson 29 of 61.

When you embed a struct as the first member of another struct, something powerful happens: the memory address of the outer struct is identical to the memory address of its first member. This is guaranteed by the C standard.

Consider our previous example:

typedef struct {
    int id;
} Parent;

typedef struct {
    Parent parent;  // First member
    int grade;
} Child;

When you create a Child variable, the Parent member sits at the very beginning of the Child's memory. This means a pointer to Child points to the exact same address as a pointer to its Parent member.

Child c;
Child* child_ptr = &c;
Parent* parent_ptr = (Parent*)child_ptr;  // Safe cast!

Both pointers hold the same address. This allows you to pass a Child* to any function expecting a Parent*:

void print_id(Parent* p) {
    printf("ID: %d\n", p->id);
}

// In main:
Child c;
c.parent.id = 42;
print_id((Parent*)&c);  // Works perfectly

This technique is the foundation of inheritance in C. A function written for the base type can operate on any derived type, as long as the base is embedded first. The cast is safe because the memory layouts align perfectly.

challenge icon

Challenge

Easy

Let's explore the first member rule by building a simple animal hierarchy. You'll create a base Animal struct and a derived Dog struct, then demonstrate how a pointer to Dog can be safely cast to a pointer to Animal.

The key insight you'll apply: when Animal is the first member of Dog, both structs share the same starting memory address. This means you can pass a Dog* to any function expecting an Animal* by casting the pointer.

You'll organize your code across three files:

  • animal.h: Define both structs with include guards. Your Animal struct should have a single field: legs (an integer representing the number of legs). Your Dog struct should embed Animal as its first member and add a name field (a character array of 50 characters). Also declare a function print_animal that takes an Animal* parameter.
  • animal.c: Implement the print_animal function. This function works with the base type—it only knows about Animal and prints how many legs the animal has.
  • main.c: Create a Dog variable and populate its fields (both the embedded animal's legs and the dog's name). Then demonstrate the first member rule by casting your Dog* to an Animal* and passing it to print_animal. Also print the dog's name separately to show the complete picture.

You will receive two inputs: the dog's name (a string) and the number of legs (an integer).

Your output should look like this:

Dog: Buddy
Legs: 4

Where Buddy is the dog's name and 4 is the number of legs. Print the dog's name first from main.c, then call print_animal with the cast pointer to display the legs.

This demonstrates how a function written for the base type (Animal) can seamlessly work with a derived type (Dog) through pointer casting—the foundation of inheritance in C.

Cheat sheet

When a struct is embedded as the first member of another struct, both structs share the same starting memory address. This is guaranteed by the C standard.

typedef struct {
    int id;
} Parent;

typedef struct {
    Parent parent;  // First member
    int grade;
} Child;

A pointer to the outer struct can be safely cast to a pointer to its first member:

Child c;
Child* child_ptr = &c;
Parent* parent_ptr = (Parent*)child_ptr;  // Safe cast - same address

This allows passing a derived type pointer to functions expecting the base type:

void print_id(Parent* p) {
    printf("ID: %d\n", p->id);
}

Child c;
c.parent.id = 42;
print_id((Parent*)&c);  // Works because memory layouts align

This technique is the foundation of inheritance in C, enabling functions written for base types to operate on derived types.

Try it yourself

#include <stdio.h>
#include <string.h>
#include "animal.h"

int main() {
    // Read input
    char name[50];
    int legs;
    scanf("%s", name);
    scanf("%d", &legs);
    
    // TODO: Create a Dog variable
    
    // TODO: Set the dog's name using strcpy
    
    // TODO: Set the number of legs (access through the embedded Animal)
    
    // TODO: Print the dog's name in format: "Dog: <name>"
    
    // TODO: Cast Dog* to Animal* and call print_animal
    // This demonstrates the first member rule!
    
    return 0;
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming