What happens before main ()[SOLVED]

Thread Starter

Pushkar1

Joined Apr 5, 2021
416
@click_here

When we start to write c-program we write some startup code before main function such as headers, Preprocessor. In the following example Delay.h and definition are called before main() function.

C:
#include<device.h>
#include"Delay.h"

#define Switch_Open  0
#define Switch_Close 1
#define Light_ON     1
#define Light_OFF    0

int main()
{
  Light = Light_OFF;
  Switch =  Switch_Open;

  if (Switch == Switch_Close)
      Light = Light_ON;
      Delay(500);
      Light = Light_OFF;
   
  return 0;
}
Let me make one thing clear that this code will not compile and run, it is just an example to understand. It's puzzle for me I don't understand What happens in a c program before main is called
 
Last edited:

John P

Joined Oct 14, 2008
2,025
It is clear that your example is for a microcontroller, and in that environment, the first code executed may well be the first line of C after main(). Or maybe the compiler inserts some useful things first, like setting all the RAM to zero, or making sure the analog inputs are turned off, or something automatic to set the operating conditions. Your compiler undoubtedly has a way to view the output, and you could take a look, and see how it functions.

If you had written C code for a computer though, you'd need to be an expert to have a chance of understanding what happens when the program starts. For most of us, we just trust that it's going to work right, and ignore how it all happens.
 

Thread Starter

Pushkar1

Joined Apr 5, 2021
416
There is usually an assembly language file called "cstartup.asm", or a similar name, which is assembled and linked, by the linkage editor into every C program. It will initialize variables, setup the stack pointer, call "main", and when "main" returns if it ever does, it will return to the OS.
I don't understand clearly what's your point

Compiler converts a C program into an executable. There are four phases for a C program to become an executable:

  1. Pre-processing
  2. Compilation
  3. Assembly
  4. Linking

These are not called before main. They are just information for the compiler on where to find definitions for things referred to in the rest of your code.
it's a hard to understand. we write the code we compile the code. We run code on hardware when there is no error
 

dcbingaman

Joined Jun 30, 2021
1,065
The preprocessor directives that use #define are nothing more than names for something else. Before the compiler does anything at all it substitutes the value for the name. This happens before the code is compiled. In fact you can do some funny things with them like this:

double r=Switch_Open.00123;

This will compile! Switch_Open is replaced with the symbol 0 and is:
double r=0.00123;

You can even do this!
double r=Switch_Open.Switch_OpenSwitch_Open123;
 

Papabravo

Joined Feb 24, 2006
21,159
I don't understand clearly what's your point

Compiler converts a C program into an executable. There are four phases for a C program to become an executable:

  1. Pre-processing
  2. Compilation
  3. Assembly
  4. Linking


it's a hard to understand. we write the code we compile the code. We run code on hardware when there is no error
My point is the that "cstartup.asm" has been assembled into an object file a long time before your program was ever conceived. The code in that object file is not affected by "your" compilation and assembly processes mentioned in steps 1 thru 3. It comes into play in step 4. of the process you outlined above. It adapts to various environments by having certain values passed to the executable like how big the data segment is so that it can do the proper initialization(s).

When the OS, or the embedded environment passes control to your executable, it goes to the code in the executable which matches the code in "cstartup.asm", the initialization is performed, and control is then passed to "main". When or if "main" returns it goes back to the code in "cstartup.asm" following the call to "main" for cleanup and exit. In the case of an embedded executable the return from main should never happen. If it does you need to do something sane and/or useful.
 
Last edited:

nsaspook

Joined Aug 27, 2009
13,081
Let's take a look at XC8 for a CRT (C Run TIme) implementation example:
https://ww1.microchip.com/downloads/en/DeviceDoc/50002737C XC8 C Compiler UG for PIC.pdf
4.3.2 Startup and Initialization
The runtime startup code performs initialization tasks that must be executed before the main() function in the C program is executed. For information on the tasks performed by this code, see 5.9 Main, Runtime Startup and Reset. The compiler will select the appropriate runtime startup code, based on the selected target device and other compiler options.

4.3.2.1 Runtime Startup Code Generation Rather than the traditional method of linking in generic, precompiled runtime startup routines, the MPLAB XC8 C Compiler determines what runtime startup code is required from the user’s program and then generates this code each time you build your project. The default operation of the driver is to keep the startup module; however, you can ask that it be deleted by using the option -mno-keep-startup (see 4.6.1.12 Keep Startup Option). If you are using the MPLAB X IDE to build, the file will be deleted unless you indicate otherwise in the Project Properties dialog. If the startup module is kept, it will be called startup.s and will be located in the current working directory. If you are using an IDE to perform the compilation, the destination directory will be dictated by the IDE. Assuming you have the default configuration selected, MPLAB X IDE stores this file in either the dist/default/production or dist/default/debug directories (based on whether you perform a production or debug build) in your project directory. Generation of the runtime startup code is an automatic process that does not require any user interaction; however, some aspects of the runtime code can be controlled, if required, using the -Wl,--no-data-init option. 4.6.12 Mapped Linker Options describes the use of this option.

The runtime startup code is executed before main(). However, if you require any special initialization to be performed immediately after Reset, you should use the powerup feature described later in 5.9.3 The Powerup Routine.
 

dcbingaman

Joined Jun 30, 2021
1,065
In some compilers/debuggers you can actually see this code being executed. If you 'break on first instruction' sometimes you can see the code that is executed before main is called.
 

Thread Starter

Pushkar1

Joined Apr 5, 2021
416
The preprocessor directives that use #define are nothing more than names for something else. Before the compiler does anything at all it substitutes the value for the name. This happens before the code is compiled.
Well that was my misunderstanding. I used to think that when the code is compiled, the compiler substitutes the value for the defined name. I found now that this happens before the code is compiled.

In some compilers/debuggers you can actually see this code being executed.
Can you tell the name of the compiler and debugger?
 

dcbingaman

Joined Jun 30, 2021
1,065
Well that was my misunderstanding. I used to think that when the code is compiled, the compiler substitutes the value for the defined name. I found now that this happens before the code is compiled.


Can you tell the name of the compiler and debugger?
Microchip MPLAB C compiler/debugger
 

click_here

Joined Sep 22, 2020
548
In the following example Delay.h and definition are called before main() function
Hey mate - Sorry for the late reply.

You've had some really good responses, so I can only add a little.

"Delay.h" isn't called before main, it just contains external objects (presumably the function "Delay")

The standards refer to two different environments: "freestanding" and "hosted". These have very different requirements for various things.

For example, main must always return an int in a hosted environment, but not a freestanding (that is allowed to have a "void main(void)")

"Hosted" is an OS - Examples of these are Windows, Linux, ...

And "freestanding" is sometimes called "bare metal programming" - This is what you'd be using.

From C99:
5.1.2 Execution environments
1 Two execution environments are defined: freestanding and hosted. In both cases, program startup occurs when a designated C function is called by the execution environment. All objects with static storage duration shall be initialized (set to their initial values) before program startup. The manner and timing of such initialization are otherwise unspecified. Program termination returns control to the execution environment


Hope this helps
 

BobTPH

Joined Jun 5, 2013
8,812
C++ code actually does have parts of your program that execute before main. The constructors for statically declared objects.

Bob
 
Top