Thread: program execution begins

  1. #1
    Registered User
    Join Date
    Oct 2022
    Posts
    99

    program execution begins

    I have a question about global variable initialization that's been causing me some confusion.

    I understand that in C programs, the execution starts from the main function. However, I'm unsure about the difference between initializing a global variable within main versus initializing it before main starts.

    Scenario 1: Declaring and Assigning Global Variable in Main

    Code:
      #include <stdio.h>
    
    // Declaration of global variable
    int x;
    
    int main() {
        // Assigning a value to the global variable within main
        x = 10;
    
        // Using the global variable
        printf("The value of x is: %d\n", x);
    
        return 0;
    }
    Scenario 2: Declaring and Assigning Global Variable Before Main

    Code:
    #include <stdio.h>
    
    // Declaration and assignment of global variable before main
    int x = 20;
    
    int main() {
        // Using the global variable
        printf("The value of x is: %d\n", x);
    
        return 0;
    }
    Could you clarify the following points for me?

    How does the program flow differ when a global variable is assigned a value within main versus being initialized before main starts?

  2. #2
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,128
    Quote Originally Posted by Kittu20 View Post
    I have a question about global variable initialization that's been causing me some confusion.

    I understand that in C programs, the execution starts from the main function. However, I'm unsure about the difference between initializing a global variable within main versus initializing it before main starts.

    // ...

    Could you clarify the following points for me?

    How does the program flow differ when a global variable is assigned a value within main versus being initialized before main starts?
    Global: int x = 20; // Harcoded "Initialization" by the compiler at compile time.

    Global: int x; // Uninitialized global variables are automatically initialized to zero
    Local: x = 20; // "Assignment" x receives the value when the line is executed

    These are VERY basic concepts that a good up to date book on the C Programming language would teach you! We are not here to teach you the language!

    I have posted the following many times!

    If you are attempting to learn from painfully inadequate online tutorials, YouTube videos, or some book claiming to teach you in a short time, then THROW THEM AWAY!

    Short of taking a course in C Programming from a qualified instructor, you need to study a good book on the C Programming Language, cover to cover, and do all the exercises at the end of each chapter! Choose one of the three listed below:

    C Programming, A Modern Approach, 2nd Edition
    Author: K. N. King

    C Primer Plus, 6th Edition
    Stephen Prata

    C How to Program, 8/e
    Deitel & Deitel

    Studying one of these books, and writing code, you will have a much better understanding of the C Programming language.

  3. #3
    Registered User
    Join Date
    Oct 2022
    Posts
    99
    Quote Originally Posted by rstanley View Post
    Global: int x = 20; // Harcoded "Initialization" by the compiler at compile time.

    Global: int x; // Uninitialized global variables are automatically initialized to zero
    Local: x = 20; // "Assignment" x receives the value when the line is executed
    .
    This means that the compiler/linker allocates memory address for a global variable and assigns a value to it before the main function is executed.

  4. #4
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,128
    Quote Originally Posted by Kittu20 View Post
    This means that the compiler/linker allocates memory address for a global variable and assigns a value to it before the main function is executed.
    It's the compiler that initializes x during the compile process. Look at the source file and the assembler code:

    Source file:
    Code:
    int x = 20;
    
    int main(void)
    {
    
      return 0;
    }
    Compile command: [gcc -s global.c]

    Look at the section"x:"

    Assembler output:
    Code:
            .file   "global.c"
            .text
            .globl  x
            .data
            .align 4
            .type   x, @object
            .size   x, 4
    x:
            .long   20
            .text
            .globl  main
            .type   main, @function
    main:
    .LFB0:
            .cfi_startproc
            pushq   %rbp
            .cfi_def_cfa_offset 16
            .cfi_offset 6, -16
            movq    %rsp, %rbp
            .cfi_def_cfa_register 6
            movl    $0, %eax
            popq    %rbp
            .cfi_def_cfa 7, 8
            ret
            .cfi_endproc
    .LFE0:
            .size   main, .-main
            .ident  "GCC: (Debian 12.2.0-14) 12.2.0"
            .section        .note.GNU-stack,"",@progbits
    The linker would resolve the definition of the global variable, and it's use in main() if used.

  5. #5
    Registered User
    Join Date
    Apr 2021
    Posts
    148
    Quote Originally Posted by Kittu20 View Post
    How does the program flow differ when a global variable is assigned a value within main versus being initialized before main starts?
    In an embedded system, there will be a runtime library function that does whatever initialization is required. However, there is unlikely to be any initialization beyond "set everything to zero". Embedded systems force the coder to set up all the "magically happens before main() is called" parts of the system themselves.

    In a "general purpose" computing environment (like your laptop or desktop) the program will be compiled into a binary image. That image includes an "initialized data" section. (Linux and Windows and Mac, this is true for all of them.) The "initialized data" part is written on disk almost exactly as it appears in memory, except for "fixups" needed due to variable load addresses. So the most common way for global variables (in C: "file scope" variables) to be intialized to a value other than zero is for the bits representing the initial value to be loaded from disk, and maybe fixed up if any addresses are contained.

    A complete object that is initialized to all zeros will typically be stored in a special "don't load any bits, just set this entire area to zero" part of the data section called .bss, this is the default for file scope data in C.

    So the code flow for a global variable initialized at compile time looks like:

    Code:
    <load image from disk>
    <perform relocation steps>
    // Look, the global variable is magically initialized!
    <set the .bss section to all zeros>
    <call main()>
    The code flow for a global variable that defaults to zero looks like this:

    Code:
    <load image from disk>
    <perform relocation steps>
    <set the .bss section to all zeros>
    // Look, the global variable is magically initialized (to zero)!
    <call main()>
    The code flow for a global variable that is assigned a value in main(), or any function called from main(), looks like:

    Code:
    <load image from disk>
    <perform relocation steps>
    <set the .bss section to all zeros>
    // Look, the global variable is defaulted to zero!
    <call main()>
    // Look, the code you wrote stored a new value where a zero used to be!
    Edit: Re-reading my post, it seems a bit snarky. Please know, I am not trying to be snarky here. The fact is, it really is this simple. This was all set up back in the late 1960's by folks who were clever and lazy, working in a painfully limited environment. So solutions that involved few instructions or (ideally) zero instructions were highly regarded, and if people needed to add extra steps on top of a cheap solution, that was on them. Even today, C++ coders brag that C++ does not make you pay for features you don't use. Minimalist solutions are part of the "ethos" of the C/C++ community.

    If you look at how C "local" variables work, it's basically "the compiler computes how many bytes of storage will be required (at compile time), and the program subtracts that many bytes from the stack pointer when you enter the function." Allocating storage for however-many local variables is reduced to one instruction and then amortized over however-many local variables there are in the function. Why are local variables not initialized? Because it is entirely likely that the initial value of one or more local variables will be the result of a function call. So spending instructions to initialize a value that will be overwritten immediately would be a waste, and we can't have that. If CPUs started to provide "adjust the stack and set everything to zero" instructions, the compiler might use them. But only if they didn't cost any cycles. In any contest between "speed" and {size, safety, security, correctness, moral goodness, American values, common sense, pounds and pence, dental hygiene, mental hygiene, Oriental hygiene, Occidental hygiene, accidental hygiene, good taste, good flavor, good hair, bad hair, Ric Flair, or Red Adair} the choice of C compiler writers is always going to be "speed." (Okay, that bit was snarky.)

    Bottom line: if there is a minimal, barely-works way to do things, that is the way C does it. And since C was used to build Unix, you can bet that the minimal way is the Unix way. And since MSDOS was "inspired by" Unix, and MacOS is now "based on" a bsd unix ... you see where this is going.
    Last edited by aghast; 05-02-2024 at 02:01 PM.

  6. #6
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    958
    Quote Originally Posted by aghast View Post
    In an embedded system, there will be a runtime library function that does whatever initialization is required. However, there is unlikely to be any initialization beyond "set everything to zero". Embedded systems force the coder to set up all the "magically happens before main() is called" parts of the system themselves.
    Unless it's a janky/non-standard compiler, there will be a C runtime that initializes variables with values before main() is called even on embedded systems. That's the case with the most popular C compilers for AVR and PIC microcontrollers and with other microcontroller C compilers like SDCC/Z88DK. It's usually just a memcpy() (or often an inlined equivalent) from the read-only program space to RAM. There's no good reason (in my mind) not to properly support initialized global variables—it won't save code space since the programmer would have to do it in main() anyway.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. And so it begins...
    By Salem in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 10-15-2007, 05:50 AM
  2. program execution
    By kris.c in forum Tech Board
    Replies: 14
    Last Post: 05-16-2007, 01:54 PM
  3. execution of a C program
    By kris.c in forum C Programming
    Replies: 7
    Last Post: 07-27-2006, 11:14 AM
  4. Program Execution
    By UnclePunker in forum C++ Programming
    Replies: 1
    Last Post: 03-27-2003, 10:07 AM
  5. When the CBoard lull begins...
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 10-28-2001, 03:35 PM

Tags for this Thread