42

I keep getting this question asked in interviews:

Write a program without using main() function.

One of my friends showed me some code using macros, but I could not understand it.

Is it really possible to write and compile a program without main()?

5
  • 17
    Seems like a pretty stupid interview question... Maybe you forgot about some detail? Commented Aug 13, 2011 at 14:20
  • 4
    Don't you just love these practical interview questions? /sarcasm Commented Aug 13, 2011 at 14:20
  • 5
    How exactly does this show whether the candidate can solve problems or fit in? It's hard enough to write and maintain readable programs, why ask about such abominations? Unless the company is called IOCCC, that is. Commented Aug 13, 2011 at 14:29
  • It depends what they mean. Did they mean "with no main() function"? or did they mean "Run code without running it from main (even indirectly)"? Commented Aug 13, 2011 at 16:10
  • "Keep getting asked"? What, did some list titled "TEH BESTEST C+ Interview Questions" just get posted on the interweb? Where are you located? With whom are you interviewing? Because I want to run in the other direction. My suggestion is that if someone asks you this question, you eliminate them. And BTW, the answer is "yes", you can "write and compile" such a program, you just cannot successfully link it (at least on a standard, hosted, compliant system). I might be splitting hairs, but that would be my smart-ass response if I was asked the question. Commented Aug 13, 2011 at 20:58

20 Answers 20

35

No, you cannot, unless you are writing a program in a free-standing environment (embedded environment, OS kernel, etc.) where the starting point need not be main(). As per the C++ standard, main() is the starting point of any program in a hosted environment.

As per the:

C++03 standard 3.6.1 Main function

A program shall contain a global function called main, which is the designated start of the program. It is implementation-defined whether a program in a freestanding environment is required to define a main function. [ Note: In a freestanding environment, start-up and termination is implementation-defined; startup contains the execution of constructors for objects of namespace scope with static storage duration; termination contains the execution of destructors for objects with static storage duration.


What is a free-standing environment & what is a hosted environment?

There are two kinds of conforming implementations defined in the C++ standard; hosted and freestanding.

A freestanding implementation is one that is designed for programs that are executed without the benefit of an operating system.

For example, an OS kernel or embedded system would be a free-standing environment.

A program using the facilities of an operating system would normally be in a hosted implementation.

From the C++03 Standard Section 1.4/7:

A freestanding implementation is one in which execution may take place without the benefit of an operating system, and has an implementation-defined set of libraries that includes certain language-support libraries.

Further, Section: 17.4.1.3.2 Freestanding implementations quotes:

A freestanding implementation has an implementation-defined set of headers. This set shall include at least the following headers, as shown in Table:

18.1 Types <cstddef>
18.2 Implementation properties <limits>
18.3 Start and termination <cstdlib>
18.4 Dynamic memory management <new>
18.5 Type identification <typeinfo>
18.6 Exception handling <exception>
18.7 Other runtime support <cstdarg>
Sign up to request clarification or add additional context in comments.

7 Comments

Are you sure? I mean everyone writing an OS kernel or embedded programs will have to do without a main function and I'd hope that such a thing wouldn't result in undefined behavior.
It seems weird to me that first you say "No you cannot." but then you quote the spec where it says that sometimes you may omit defining it.
@ Johannes Schaub - litb: Ah, I will add the exception of freestanding environments.
@Voo: No freestanding environments like embedded programs or OS kernels can omit the main, check the quote from the standard.
Various pre-processor concatenation tricks with the ## operator isn't really changing the name of main - main is still there after the pre-processor translation phases. So any answers suggesting tricks with ## are perhaps more interested in showing off entertaining obfuscation tricks (shamelessly plagiarized from external sources) than to answer the actual question.
|
23

Within standard C++ a main function is required, so the question does not make sense for standard C++.

Outside of standard C++ you can for example write a Windows specific program and use one of Microsoft's custom startup functions (wMain, winMain, and wWinmain). In Windows you can also write the program as a DLL and use rundll32 to run it.

Apart from that, you can make your own little runtime library. At one time that was a common sport.

Finally, you can get clever and retort that according to the standard's ODR rule main isn't "used", so any program qualifies. Bah! Although, unless the interviewers have unusual good sense of humor (and they wouldn't have asked the question if they had), they'll not think that that's a good answer.

3 Comments

Oh. I'd planned to just let this answer B, with mistake for all 2 C. (OK, just watched Star Wars movie). It was complemented and corrected by e.g. Als' answer and Johannes Schaub's answer. Now, in case a causal later reader doesn't see it: a frestanding environment, e.g. such as a compiler for a DSP, allows other startup function than main.
I'm not the anonymous downvoter - but I suspect its a vote against this being the accepted answer, when it is not accurate. Its a really poor interview question - but this answer is misleading as it is only true for the (admittedly more common) hosted environment.
Its worth noting while we can't actually omit a defined main, we can have a program that doesn't rely on it. In other words, you CAN have a program with an empty main function that runs other code on its own-usually in some global instanced or static class. For example class abc { public: abc() { printf("this code runs on its own"); } abc_instance;
14

Sample program without a visible main function.

/* 
    7050925.c 
    $ gcc -o 7050925 7050925.c
*/

#include <stdio.h>
#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)

int begin()
{
        printf("How mainless!\n");
}

From: http://learnhacking.in/c-program-without-main-function/

2 Comments

Actually, this is as good as #define begin() main(), You can just add a lot of lesser known/popular C/C++ constructs and mask it but the main has to be defined for a hosted environment implementation,Adding this comment here because without this the answer might be little misleading to newbies.
This code is not without main. gcc -E file.c would give you the code which is actually being compiled.
13

main means an entry point, a point from which your code will start executing. Although main is not the first function to run. There are some more code which runs before main and prepares the environment to make your code run. This code then calls main . You can change the name of the main function by recompiling the code of the startup file crt0.c and changing the name of the main function. Or you can do the following:

#include <stdio.h>

extern void _exit (register int code);

_start()
{
  int retval;
  retval = my_main ();
  _exit(retval);
}

int my_main(void)
{
  printf("Hello\n");
  return 0;
}

Compile the code with:

gcc -o no_main no_main.c -nostartfiles

The -nostartfiles will not include the default startup file. You point to the main entry file with the _start.

main is nothing but a predefined entry point for the user code. Therefore you can name it whatever, but at the end of the day you do need an entry point. In C/C++ and other languages, the name is selected as main. If you make another language or hack the sources of these language compilers, then you can change the name of main to pain, but it will bring pain, as it will violate the standards.

But manipulating the entry function name is useful for kernel code, the first function to run in the kernel, or code written for embedded systems.

Comments

9

They may refer to a program written for a free-standing implementation. The C++ Standard defines two sorts of implementations. One is a hosted implementation. Programs written for those implementations are required to have a main function.

But otherwise, no main function is required if the free-standing implementation doesn't require one. This is useful for operating system kernels or embedded system programs that don't run under an operating system.

Comments

9

Yes

$ cat > hwa.S
write = 0x04
exit  = 0xfc
.text
_start:
        movl    $1, %ebx
        lea     str, %ecx
        movl    $len, %edx
        movl    $write, %eax
        int     $0x80
        xorl    %ebx, %ebx
        movl    $exit, %eax
        int     $0x80
.data
str:    .ascii "Hello, world!\n"
len = . -str
.globl  _start
$ as -o hwa.o hwa.S
$ ld hwa.o
$ ./a.out
Hello, world!

The kernel that really runs an executable knows nothing about internal symbols. It just transfers to an entry point specified in binary in the executable image header.

The reason you need a main is because normally your "main program" is really just another module. The entry point is in library-provided startup code written in some combination of C and assembly, and that library code just happens to call main, so you normally need to provide one. But run the linker directly and you don't.

To include a C module1...

$ cat > nomain.S
.text
.globl start
start:
        call   _notmain
$ as -o nomain.o nomain.S
$ cat > notmain.c
#include <unistd.h>

void notmain(void) {
  write(1, "hi\n", 3);
  _exit(0);
}
$ cc -c notmain.c
$ ld -w nomain.o notmain.o -lc
$ ./a.out
hi

1. And I'm also switching to x86-64 here.

Comments

6

Yes, it possible to compile without main, but you cannot pass the linking phase though.

g++ -c noMain.cpp -o noMain.o

Comments

4

"Without using main" might also mean that no logic is allowed within main, but the main itself exists. I can imagine the question had this cleared out, but since it's not cleared here, this is another possible answer:

struct MainSub
{
   MainSub()
   {
      // Do some stuff
   }
};

MainSub mainSub;

int main(int argc, char *argv[]) { return 0; }

The stuff in MainSub's constructor will execute before the unusable main is executed, and you can place the program's logic there. This of course requires C++, and not C (also not clear from the question).

5 Comments

Why would MainSub::MainSub() be executed? You don't construct a MainSub object anywhere?
@Dan, yes I do. Right below the struct's definition, and above int main.
Oh right, I thought that would be just a declaration. If it were a primitive i.e. int, its value would be undefined, no?
@Dan, if it were an int, it would have been initialized to 0.
You learn something new about C++ all the time. I never knew that... though I did have to test it ;) +1 for teaching me something new.
3

As long as you are using g++, you could change your entry point with linker option -e, so the following code and compile command may let you create a program without a main() function:

#import <iostream>

class NoMain
{
public:
    NoMain()
    {
        std::cout << "Hello, World!!" << std::endl;
        exit(0);
    }
} mainClass;

I gave the filename as noname.cpp, and the compile option is:

g++ nomain.cpp -Wl,-e,_mainClass -v

To tell the truth, I didn't fully understand why the code can works fine. I suspect that the address of global variable mainClass is the same to constructor of NoMain class. However, I also have several reasons that I could tell my guess may not correct.

1 Comment

Why "#import"? Related: What is the difference between #import and #include in C?. E.g., "#import is not standard and can mean different things for different compilers."
2

It will probably not work with all linkers, but it's at least possible to trick ld (I'm running version 2.24.51.20140918) into thinking there is a main-function by doing this:

int main[] {};

Or even just

int main;

You can then apply one of the aforementioned tricks to let the program execute some code, e.g., through the use of a constructor:

struct Main
{
    Main()
    {
        cout << "Hello, World!!\n";
        exit(0);
    }
} main_;

The exit(0) is to prevent the array from being "called".

Comments

2

When C or C++ code runs, it executes at a known start address. The code here initialises the run-time environment, initialises the stack pointer, performs data initialisation, calls static constructors, and then jumps to main().

The code that does this is linked with your code at build time by the linker. In GCC, it is usually in crt0.s, and with a commercial compiler, it is unlikely that this code will be available to you.

In the end, it has to start somewhere and main() is just a symbolic name for that location. It is specified by the language standard, so that developers know what to call it. Otherwise, code would not be portable from one toolchain to another.

If you are writing code for a 'bare-metal' system without any OS or at least no OS in the sense of a process loader (embedded systems often include an RTOS kernel that is started after main()), then you can in theory call the C code entry point whatever you wish since you usually have complete control over run-time start-up code. But to do so would be foolish and somewhat perverse.

Some RTOS environments such as VxWorks, and most application frameworks in general include main()) or its equivalent) within their own library code, so that it runs before the user application code. For example, VxWorks applications start from usrAppInit(), and Win32 applications start from WinMain().

Comments

1

Arriving late to the party - there are lot of questionable answers to this old post. A better one to use as reference might be What should main() return in C and C++? for example the answer by yours sincerely there, with relevant quotes from the language standards.

Brief summary:

  • Both C and C++ make a difference between hosted programs and freestanding programs. Hosted programs are those running on top of an OS. Freestanding programs are either the OS itself or a program written for a RTOS, or a so-called "bare-metal" embedded system with no OS at all.

    A compiler + all the standard libs supported is formally called an implementation by the standards. And so a hosted implementation is a compiler + standard libs for an OS environment, whereas a freestanding implementation is an embedded systems compiler. Freestanding implementations are allowed by the standard to implement a minimal subset of the standard library.

  • For freestanding programs, both C and C++ allow implementation-defined forms of the function first executed. Implementation-defined meaning that the compiler might chose a different name and format for the function first executed and will document that name and format.

    It does not mean that the programmer gets to decide the name or format of that function - anyone attempting such is writing a non-conforming/ill-formed program. And so such programs are to regarded as extensions beyond the language - it is something else than C or C++.

  • C++ is a bit pickier than C since it forces freestanding implementations that want to use the name main for the implementation-defined form to also use the format int main(). This is quite inconvenient for bare metal programs since it sometimes creates a bit of useless overhead where the "CRT" calls main. C is more relaxed and has no such requirement, and so the most common implementation-defined form in freestanding systems is void main (void).

  • Implementation-defined forms are also (arguably) allowed for hosted systems. Those familiar with Windows programming may recognize WinMain, for example. C allows such implementation-defined forms, but it is debatable if C++ does or if such forms are just non-conforming/ill-formed.

    Once again, implementation-defined forms are only allowed if the compiler supports them and document them. The programmer cannot go ahead and invent their own forms.

Comments

1

I think the macro reference was to renaming the main function. The following is not my code, and demonstrates this. The compiler still sees a main function though, but technically there isn't any main from a source point of view. I got it here http://www.exforsys.com/forum/c-and-c/96849-without-main-function-how-post412181.html#post412181

#include<stdio.h>
#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)

int begin()
{
  printf(" hello ");
}

1 Comment

The link seems to be (effectively) broken (empty page).
1

Disregarding specific language standards, most linking loader provides some means to declare a function name (entry point) which must be executed when the binary is loaded into memory.

For the old school C language, the default was something like 'start' or '_start', defined in so-called CRT (C runtime?), which does several housekeeping jobs needed for C standard functions, such as preparing the memory heap, initialising static variable areas, parsing the command line into argc/argv, etc.

Possibly, you could override the entry point function if you take enough care not to use the standard functions which requires those housekeeping things (e.g., malloc(), free(), printf(), any class definitions have custom constructor, etc.) It is quite restrictive, but not impossible if you use functions provided by the OS, not by the standard C runtime.

For example, you can make a simple Hello, World! program using the write() function on file descriptor 1.

Comments

1

Write a class and print your name in the constructor of that class and declare a global object of that class. So the class' constructor gets executed before main. So you can leave the main empty and still print your name.

class MyClass
{
   myClass()
   {
       cout << "printing my name..." <<endl;
   }
};

MyClass gObj; // This will trigger the constructor.

int main()
{
   // Nothing here...
}

Comments

1

Yes, you can do it by changing the entry point of the C language from main() to _start.

Here is the code:

#include <stdio.h>
#include <stdlib.h>

int sid()
{
    printf("Hello, World!\n");
    exit(0);
}

Then run the code using the GCC compiler. Let's assume that you have saved the file with the name of test.c then.

gcc -nostartfiles test.c
./a.out

Comments

0

It depends what they mean.

Did they mean:

Write a program with no main() function.

Then generally speaking no. But there are ways to cheat.

  • You can use the preprocessor to hide main() in plain sight.
  • Most compilers allow you to specify the entry point into your code. By default, it is main(int, char*[]).

Or did they mean:

Write a program that runs code without using main (to run your code).

This is a relatively simple trick. All objects in the global namespace run their constructors before main() is entered and destruction after main() exits. Thus, all you need to do is define a class with a constructor that runs the code you want, and then create an object in the global namespace.

Note: The compiler is allowed to optimize these objects for delayed load (but usually does not), but to be safe, just put the global in the same file as the main function (that can be empty).

Comments

0
  1. Using a macro that defines main

    #include <stdio.h>
    #define fun main
    
    int fun(void)
    {
        printf("Stack Overflow");
        return 0;
    }
    

    Output:

    Stack Overflow
    
  2. Using the token-pasting operator

    The above solution has the word ‘main’ in it. If we are not allowed to even write main, we can use the token-pasting operator (see this for details)

    #include <stdio.h>
    
    #define fun m##a##i##n
    
    int fun()
    {
        printf("Stack Overflow");
        return 0;
    }
    

Comments

0

By using C++ constructors you write a C++ program without the main function with nothing it it. Let's say for example we can print "Hello, World!" without writing anything in the main function as follows:

class printMe {
    private:
    //

    public:

        printMe() {
            cout << "Hello, World!" << endl;
        }

    protected:
    //

} obj;

int main() {}

Comments

-1

Function main is only a default label for an address where the program will start execution. So technically yes it’s possible, but you have to set the name of the function that will start execution in your environment.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.