Question

The section $3.6.1/1 from the C++ Standard reads,

A program shall contain a global function called main, which is the designated start of the program.

Now consider this code,

int square(int i) { return i*i; }
int user_main()
{ 
    for ( int i = 0 ; i < 10 ; ++i )
           std::cout << square(i) << endl;
    return 0;
}
int main_ret= user_main();
int main() 
{
        return main_ret;
}

This sample code does what I intend it to do, i.e printing the square of integers from 0 to 9, before entering into the main() function which is supposed to be the "start" of the program.

I also compiled it with -pedantic option, GCC 4.5.0. It gives no error, not even warning!

So my question is,

Is this code really Standard conformant?

If it's standard conformant, then does it not invalidate what the Standard says? main() is not start of this program! user_main() executed before the main().

I understand that to initialize the global variable main_ret, the use_main() executes first but that is a different thing altogether; the point is that, it does invalidate the quoted statement $3.6.1/1 from the Standard, as main() is NOT the start of the program; it is in fact the end of this program!


EDIT:

How do you define the word 'start'?

It boils down to the definition of the phrase "start of the program". So how exactly do you define it?

Was it helpful?

Solution

No, C++ does a lot of things to "set the environment" prior to the call of main; however, main is the official start of the "user specified" part of the C++ program.

Some of the environment setup is not controllable (like the initial code to set up std::cout; however, some of the environment is controllable like static global blocks (for initializing static global variables). Note that since you don't have full control prior to main, you don't have full control on the order in which the static blocks get initialized.

After main, your code is conceptually "fully in control" of the program, in the sense that you can both specify the instructions to be performed and the order in which to perform them. Multi-threading can rearrange code execution order; but, you're still in control with C++ because you specified to have sections of code execute (possibly) out-of-order.

OTHER TIPS

You are reading the sentence incorrectly.

A program shall contain a global function called main, which is the designated start of the program.

The standard is DEFINING the word "start" for the purposes of the remainder of the standard. It doesn't say that no code executes before main is called. It says that the start of the program is considered to be at the function main.

Your program is compliant. Your program hasn't "started" until main is started. The constructor is called before your program "starts" according to the definition of "start" in the standard, but that hardly matters. A LOT of code is executed before main is ever called in every program, not just this example.

For the purposes of discussion, your constructor code is executed prior to the 'start' of the program, and that is fully compliant with the standard.

Your program will not link and thus not run unless there is a main. However main() does not cause the start of the execution of the program because objects at file level have constructors that run beforehand and it would be possible to write an entire program that runs its lifetime before main() is reached and let main itself have an empty body.

In reality to enforce this you would have to have one object that is constructed prior to main and its constructor to invoke all the flow of the program.

Look at this:

class Foo
{
public:
   Foo();

 // other stuff
};

Foo foo;

int main()
{
}

The flow of your program would effectively stem from Foo::Foo()

You tagged the question as "C" too, then, speaking strictly about C, your initialization should fail as per section 6.7.8 "Initialization" of the ISO C99 standard.

The most relevant in this case seems to be constraint #4 which says:

All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.

So, the answer to your question is that the code is not compliant to the C standard.

You would probably want to remove the "C" tag if you were only interested to the C++ standard.

Section 3.6 as a whole is very clear about the interaction of main and dynamic initializations. The "designated start of the program" is not used anywhere else and is just descriptive of the general intent of main(). It doesn't make any sense to interpret that one phrase in a normative way that contradicts the more detailed and clear requirements in the Standard.

The compiler often has to add code before main() to be standard compliant. Because the standard specifies that initalization of globals/statics must be done before the program is executed. And as mentioned, the same goes for constructors of objects placed at file scope (globals).

Thus the original question is relevant to C as well, because in a C program you would still have the globals/static initialization to do before the program can be started.

The standards assume that these variables are initialized through "magic", because they don't say how they should be set before program initialization. I think they considered that as something outside the scope of a programming language standard.

Edit: See for example ISO 9899:1999 5.1.2:

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.

The theory behind how this "magic" was to be done goes way back to C's birth, when it was a programming language intended to be used only for the UNIX OS, on RAM-based computers. In theory, the program would be able to load all pre-initialized data from the executable file into RAM, at the same time as the program itself was uploaded to RAM.

Since then, computers and OS have evolved, and C is used in a far wider area than originally anticipated. A modern PC OS has virtual addresses etc, and all embedded systems execute code from ROM, not RAM. So there are many situations where the RAM can't be set "automagically".

Also, the standard is too abstract to know anything about stacks and process memory etc. These things must be done too, before the program is started.

Therefore, pretty much every C/C++ program has some init/"copy-down" code that is executed before main is called, in order to conform with the initialization rules of the standards.

As an example, embedded systems typically have an option called "non-ISO compliant startup" where the whole initialization phase is skipped for performance reasons, and then the code actually starts directly from main. But such systems don't conform to the standards, as you can't rely on the init values of global/static variables.

Your "program" simply returns a value from a global variable. Everything else is initialization code. Thus, the standard holds - you just have a very trivial program and more complex initialization.

main() is a user function called by the C runtime library.

see also: Avoiding the main (entry point) in a C program

Seems like an English semantics quibble. The OP refers to his block of code first as "code" and later as the "program." The user writes the code, and then the compiler writes the program.

main is called after initializing all the global variables.

What the standard does not specify is the order of initialization of all the global variables of all the modules and statically linked libraries.

Yes, main is the "entry point" of every C++ program, excepting implementation-specific extensions. Even so, some things happen before main, notably global initialization such as for main_ret.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top