Skip to content

C Scope and Linkage — Complete Guide

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about C Scope and Linkage. We cover key concepts, practical examples, and best practices to help you master this topic.

C scope and linkage determine where variables are visible in your program. Scope refers to the region where a variable can be accessed. Linkage controls whether the same name refers to the same object across different source files.

Why It Matters

Understanding scope prevents name collisions and unintended variable modification. Linkage is essential for multi-file programs where you need to share variables across source files while controlling access. Proper use of static and extern is a hallmark of well-organized C code.

Real-World Use

Large projects like the Linux kernel use static extensively to hide internal functions and variables within a translation unit. Libraries expose only their public API through extern declarations in header files. Embedded Systems use static to prevent symbol clashes in memory-constrained environments.

What You Will Learn

  • Local (block) scope for temporary variables
  • Global (file) scope for shared state
  • Static variables: file-level and function-level
  • The extern keyword for cross-file access
  • Linkage types: external, internal, none

Learning Path

flowchart LR
  A[Functions] --> B[Scope & Linkage\nYou are here]
  B --> C[Recursion]
  C --> D[Variable Arguments]
  style B fill:#f90,color:#fff

Scope Types

Scope defines where a variable can be accessed:

  1. Block scope: variables declared inside a function or block {}
  2. File scope: variables declared outside any function (globals)
  3. Function Prototype scope: parameter names in prototypes
  4. Function scope: labels (for goto)
#include <stdio.h>

// File scope (global) -- accessible everywhere in this file
int global_var = 100;

// Static file scope -- only in this file (internal linkage)
static int file_static = 200;

void demo_func(void) {
    // Block scope -- only in this function
    int local_var = 10;

    // Static local -- persists across calls, initialized once
    static int call_count = 0;
    call_count++;

    {
        // Nested block scope
        int inner = 999;
        printf("Inner: %d\n", inner);
    }
    // printf("%d", inner);  // ERROR: inner out of scope

    printf("local: %d, global: %d, count: %d\n",
           local_var, global_var, call_count);
}

int main() {
    demo_func();  // count: 1
    demo_func();  // count: 2
    demo_func();  // count: 3

    printf("global: %d\n", global_var);
    printf("file_static: %d\n", file_static);
    return 0;
}

Output:

Inner: 999
local: 10, global: 100, count: 1
Inner: 999
local: 10, global: 100, count: 2
Inner: 999
local: 10, global: 100, count: 3
global: 100
file_static: 200

The static Keyword

static has different meanings depending on context:

Static Local Variables

A static local variable retains its value between function calls. It is initialized only once, when the program starts:

#include <stdio.h>

int next_id(void) {
    static int id = 0;  // Initialized once
    return id++;
}

int main() {
    printf("%d\n", next_id());  // 0
    printf("%d\n", next_id());  // 1
    printf("%d\n", next_id());  // 2
    return 0;
}

Static File-Level Variables and Functions

At file scope, static gives a variable or function internal linkage -- it is only visible within that translation unit:

// file_helper.c
static int internal_counter = 0;  // Not visible outside this file

static void helper_function(void) {  // Not visible outside
    internal_counter++;
}

void public_function(void) {  // Visible outside
    helper_function();
}

The extern Keyword

extern tells the compiler that a variable or function is defined in another translation unit:

// file1.c
#include <stdio.h>

int shared = 42;  // Definition (allocates storage)
void print_shared(void);  // Declaration

int main() {
    printf("Before: %d\n", shared);
    modify_shared();
    printf("After: %d\n", shared);
    return 0;
}

// file2.c
extern int shared;  // Declaration only (no storage allocated)

void modify_shared(void) {
    shared = 99;
}

extern vs Definition

int x;          // Definition (tentative, becomes definition)
extern int x;   // Declaration only (not a definition)
extern int x = 5; // Definition (initializer makes it a definition)

Linkage Types

C defines three types of linkage:

Linkage Keyword Scope Same name in different files
External (none) or extern File Refers to same object
Internal static File Refers to different objects
None (none, block scope) Block Always different
static int a;     // Internal linkage
int b;            // External linkage
extern int c;     // External linkage (declaration)

void func(void) {
    int x;        // No linkage
    static int y; // No linkage (different from file-static!)
}

Variable Shadowing

When a local variable has the same name as a global variable, the local shadows (hides) the global:

#include <stdio.h>

int value = 100;  // Global

int main() {
    int value = 200;  // Local shadows global
    printf("Local: %d\n", value);   // 200

    // Access global with extern (inside a block)
    {
        extern int value;
        printf("Global: %d\n", value);  // 100
    }
    return 0;
}

Output:

Local: 200
Global: 100

Common Mistakes

  1. Variable shadowing: a local variable unintentionally hides a global with the same name
  2. Forgetting static: file-level functions should be static unless they are part of the public API
  3. Multiple definitions: defining the same global in two source files causes linker errors
  4. Assuming block scope works like JavaScript: C has no hoisting -- variables exist from declaration point
  5. Modifying static variable thinking it is thread-safe: static variables are shared across threads and need synchronization

Practice Questions

  1. What is the difference between local and global scope? Local is within a function block; global is throughout the file.
  2. What does static do to a local variable? It makes the variable persist across function calls, retaining its value.
  3. What does extern do? It declares a variable defined in another source file without allocating storage.
  4. What is variable shadowing? When a local variable has the same name as a global variable, hiding the global in that scope.
  5. Challenge: Write a counter function using a static local variable that returns 0, 1, 2, ... on successive calls.

Mini Project: Scoped Logger

#include <stdio.h>

static int log_level = 2;  // Internal linkage

void set_log_level(int level) {
    log_level = level;
}

void log_message(const char *msg, int level) {
    if (level <= log_level) {
        printf("[%s] %s\n",
               level == 0 ? "ERROR" :
               level == 1 ? "WARN"  : "INFO",
               msg);
    }
}

int main() {
    log_message("Starting program", 2);
    log_message("This is a warning", 1);
    set_log_level(0);
    log_message("This should not appear", 2);  // Filtered
    log_message("Critical error", 0);           // Appears
    return 0;
}

FAQ

Can I access a local variable from another function?

No. Local variables are destroyed when the function returns. Use pointers, return values, or static variables.

What is the default linkage of global variables?

External -- they can be accessed from other source files with an extern declaration.

What is internal linkage?

Variables and functions marked static at file scope have internal linkage. They are only visible within their own translation unit.

Can a variable have no linkage?

Yes. Local variables (non-static) have no linkage. Each function call creates a new instance on the stack.

Should I use global variables?

Sparingly. Globals make code hard to test, reason about, and parallelize. Pass parameters or use structs instead.

What is Next

Proceed to Recursion to learn about recursive functions and the call stack.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro

Home Browse C