c
examples
examples.cš§c
/*
* =============================================================================
* SCOPE AND STORAGE CLASSES - EXAMPLES FILE
* =============================================================================
*
* This file demonstrates variable scope and storage classes in C.
* Topics covered: auto, register, static, extern, local/global scope
*
* Compilation: gcc examples.c -o examples
* Execution: ./examples
* =============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
/*
* =============================================================================
* GLOBAL VARIABLES SECTION
* =============================================================================
* Variables declared outside all functions have file scope (global scope).
* They are accessible from any function in this file.
*/
int globalVar = 100; // Global variable (file scope)
static int staticGlobalVar = 200; // Static global (file scope, limited linkage)
/*
* =============================================================================
* EXAMPLE 1: Block Scope (Local Variables)
* =============================================================================
* Variables declared inside a block { } are only accessible within that block.
*/
void example1_block_scope(void) {
printf("\n=== Example 1: Block Scope ===\n");
int outerVar = 10; // Scope: entire function
printf("Outer variable: %d\n", outerVar);
{
// Inner block starts here
int innerVar = 20; // Scope: only this inner block
printf("Inner variable: %d\n", innerVar);
printf("Outer variable (from inner block): %d\n", outerVar);
}
// Inner block ends - innerVar is destroyed
// printf("innerVar: %d\n", innerVar); // ERROR! innerVar not accessible
printf("Outer variable still accessible: %d\n", outerVar);
// Demonstrating nested blocks
for (int i = 0; i < 3; i++) {
int loopVar = i * 10; // New variable each iteration
printf("Loop iteration %d: loopVar = %d\n", i, loopVar);
}
// i and loopVar not accessible here
}
/*
* =============================================================================
* EXAMPLE 2: Function Scope and Global Variables
* =============================================================================
* Global variables can be accessed from any function.
*/
void modifyGlobal(void) {
globalVar = 150; // Modifying global variable
printf(" Inside modifyGlobal: globalVar = %d\n", globalVar);
}
void readGlobal(void) {
printf(" Inside readGlobal: globalVar = %d\n", globalVar);
}
void example2_global_scope(void) {
printf("\n=== Example 2: Global Scope ===\n");
printf("Initial globalVar: %d\n", globalVar);
readGlobal();
modifyGlobal();
readGlobal();
// Modify from this function too
globalVar = 300;
printf("After modification: globalVar = %d\n", globalVar);
// Reset for other examples
globalVar = 100;
}
/*
* =============================================================================
* EXAMPLE 3: The auto Storage Class
* =============================================================================
* auto is the default storage class for local variables.
* Variables are created and destroyed with each function call.
*/
void example3_auto_storage(void) {
printf("\n=== Example 3: auto Storage Class ===\n");
// These are implicitly auto
int x = 10;
int y = 20;
// Explicit auto (rarely used in modern C)
auto int z = 30;
printf("auto variables (implicit): x = %d, y = %d\n", x, y);
printf("auto variable (explicit): z = %d\n", z);
printf("\nDemonstrating auto variable recreation:\n");
}
void autoDemo(void) {
int count = 0; // Recreated each call
count++;
printf(" count = %d (always 1 because recreated each call)\n", count);
}
void callAutoDemo(void) {
printf("Calling autoDemo 3 times:\n");
autoDemo();
autoDemo();
autoDemo();
}
/*
* =============================================================================
* EXAMPLE 4: The static Storage Class - Local Static Variables
* =============================================================================
* Static local variables retain their value between function calls.
* They are initialized only once.
*/
void staticCounter(void) {
static int count = 0; // Initialized once, persists between calls
count++;
printf(" staticCounter called %d time(s)\n", count);
}
void example4_static_local(void) {
printf("\n=== Example 4: static Local Variables ===\n");
printf("Calling staticCounter 5 times:\n");
for (int i = 0; i < 5; i++) {
staticCounter();
}
printf("\nNotice how count persists between calls!\n");
}
/*
* =============================================================================
* EXAMPLE 5: static vs auto Comparison
* =============================================================================
* Comparing behavior of static and auto variables.
*/
void autoFunction(void) {
int autoVar = 0; // Reset each call
autoVar++;
printf(" autoVar = %d\n", autoVar);
}
void staticFunction(void) {
static int staticVar = 0; // Persists between calls
staticVar++;
printf(" staticVar = %d\n", staticVar);
}
void example5_static_vs_auto(void) {
printf("\n=== Example 5: static vs auto Comparison ===\n");
printf("Calling autoFunction 3 times:\n");
autoFunction();
autoFunction();
autoFunction();
printf("\nCalling staticFunction 3 times:\n");
staticFunction();
staticFunction();
staticFunction();
printf("\nauto resets; static persists.\n");
}
/*
* =============================================================================
* EXAMPLE 6: Static Global Variables (File Scope Limitation)
* =============================================================================
* static global variables are only accessible within the same file.
*/
void example6_static_global(void) {
printf("\n=== Example 6: static Global Variables ===\n");
printf("staticGlobalVar = %d\n", staticGlobalVar);
printf("This variable is only accessible in this file.\n");
printf("Other .c files cannot access staticGlobalVar.\n");
staticGlobalVar = 250;
printf("Modified staticGlobalVar = %d\n", staticGlobalVar);
}
/*
* =============================================================================
* EXAMPLE 7: The register Storage Class
* =============================================================================
* register suggests storing variable in CPU register for faster access.
* Cannot take address of register variable.
*/
void example7_register_storage(void) {
printf("\n=== Example 7: register Storage Class ===\n");
register int i;
register int sum = 0;
// Fast loop with register variable
printf("Calculating sum of 1 to 100:\n");
for (i = 1; i <= 100; i++) {
sum += i;
}
printf("Sum = %d\n", sum);
// Demonstrating limitation
printf("\nNote: Cannot take address of register variable.\n");
printf("// int *ptr = &i; // This would cause an error\n");
// Regular variable for comparison
int regular = 10;
int *ptr = ®ular;
printf("Address of regular variable: %p\n", (void*)ptr);
}
/*
* =============================================================================
* EXAMPLE 8: extern Declaration (Same File)
* =============================================================================
* extern can reference a variable defined later in the same file.
*/
void example8_extern_same_file(void); // Forward declaration
// Variable defined below, but we use extern to reference it first
extern int lateDefinedVar;
void example8_extern_same_file(void) {
printf("\n=== Example 8: extern Declaration ===\n");
printf("lateDefinedVar = %d\n", lateDefinedVar);
printf("This variable is defined below but accessible via extern.\n");
lateDefinedVar = 999;
printf("Modified lateDefinedVar = %d\n", lateDefinedVar);
}
int lateDefinedVar = 500; // Definition (memory allocated here)
/*
* =============================================================================
* EXAMPLE 9: Variable Shadowing
* =============================================================================
* Inner scope variables can "shadow" outer scope variables with same name.
*/
int shadowTest = 1000; // Global
void example9_shadowing(void) {
printf("\n=== Example 9: Variable Shadowing ===\n");
printf("Global shadowTest: %d\n", shadowTest);
int shadowTest = 2000; // Shadows global variable
printf("Local shadowTest (shadows global): %d\n", shadowTest);
{
int shadowTest = 3000; // Shadows the local variable
printf("Inner block shadowTest: %d\n", shadowTest);
}
printf("Local shadowTest (after inner block): %d\n", shadowTest);
// The global is unchanged
printf("\nNote: Global variable is unchanged, just hidden.\n");
}
/*
* =============================================================================
* EXAMPLE 10: Practical Use of static - Singleton Pattern
* =============================================================================
* Using static to implement a simple singleton-like pattern.
*/
int* getSingletonValue(void) {
static int singleton = 42; // Created once, persists
return &singleton; // Return address (safe because static)
}
void example10_singleton_pattern(void) {
printf("\n=== Example 10: Singleton with static ===\n");
int *ptr1 = getSingletonValue();
int *ptr2 = getSingletonValue();
printf("First call: value = %d, address = %p\n", *ptr1, (void*)ptr1);
printf("Second call: value = %d, address = %p\n", *ptr2, (void*)ptr2);
if (ptr1 == ptr2) {
printf("Same address! Static variable persists.\n");
}
// Modify through one pointer
*ptr1 = 100;
printf("After *ptr1 = 100: *ptr2 = %d\n", *ptr2);
}
/*
* =============================================================================
* EXAMPLE 11: Function Call Counter
* =============================================================================
* Practical example: counting function invocations.
*/
int getCallCount(void) {
static int callCount = 0;
return ++callCount;
}
void example11_call_counter(void) {
printf("\n=== Example 11: Function Call Counter ===\n");
printf("Function call counts:\n");
for (int i = 0; i < 5; i++) {
printf(" Call #%d: getCallCount() = %d\n", i + 1, getCallCount());
}
}
/*
* =============================================================================
* EXAMPLE 12: Initialization Differences
* =============================================================================
* Comparing initialization behavior of different storage classes.
*/
int uninitGlobal; // Default: 0
static int uninitStaticGlobal; // Default: 0
void example12_initialization(void) {
printf("\n=== Example 12: Initialization Behavior ===\n");
int uninitAuto; // Default: garbage (undefined)
static int uninitStatic; // Default: 0
printf("Uninitialized global: %d (default 0)\n", uninitGlobal);
printf("Uninitialized static global: %d (default 0)\n", uninitStaticGlobal);
printf("Uninitialized static local: %d (default 0)\n", uninitStatic);
printf("Uninitialized auto (WARNING - garbage): %d\n", uninitAuto);
printf("\nAlways initialize auto variables explicitly!\n");
}
/*
* =============================================================================
* EXAMPLE 13: Memory Addresses - Storage Location
* =============================================================================
* Showing where different variables are stored in memory.
*/
void example13_memory_locations(void) {
printf("\n=== Example 13: Memory Locations ===\n");
int autoVar = 10;
static int staticVar = 20;
printf("Variable addresses:\n");
printf(" Global variable: %p\n", (void*)&globalVar);
printf(" Static global: %p\n", (void*)&staticGlobalVar);
printf(" Static local: %p\n", (void*)&staticVar);
printf(" Auto (local): %p\n", (void*)&autoVar);
printf("\nNotice: static variables have similar addresses (data segment)\n");
printf("Auto variables are on the stack (different memory region)\n");
}
/*
* =============================================================================
* EXAMPLE 14: Returning Pointer to Static Variable
* =============================================================================
* Safe to return pointer to static local (persists after function returns).
*/
int* safeReturn(void) {
static int value = 100;
return &value; // Safe - static persists
}
// DANGEROUS - Don't do this!
// int* unsafeReturn(void) {
// int value = 100;
// return &value; // UNSAFE - auto destroyed after return
// }
void example14_safe_return(void) {
printf("\n=== Example 14: Safe Pointer Return ===\n");
int *ptr = safeReturn();
printf("Returned pointer to static: %d\n", *ptr);
*ptr = 200;
printf("Modified through pointer: %d\n", *safeReturn());
printf("\nReturning pointers to static variables is safe.\n");
printf("NEVER return pointers to auto (local) variables!\n");
}
/*
* =============================================================================
* MAIN FUNCTION
* =============================================================================
*/
int main(void) {
printf("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
printf("ā SCOPE AND STORAGE CLASSES - DEMONSTRATION PROGRAM ā\n");
printf("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
example1_block_scope();
example2_global_scope();
example3_auto_storage();
callAutoDemo();
example4_static_local();
example5_static_vs_auto();
example6_static_global();
example7_register_storage();
example8_extern_same_file();
example9_shadowing();
example10_singleton_pattern();
example11_call_counter();
example12_initialization();
example13_memory_locations();
example14_safe_return();
printf("\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
printf("ā EXAMPLES COMPLETED ā\n");
printf("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
return 0;
}