Programming
C Language
C++ Language
Main() Function
Code Return Values

What should main() return in C and C++?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In both C and C++, main() should return an int. That return value becomes the program’s exit status, which the operating system and calling processes can inspect to determine whether the program succeeded or failed.

Core Sections

Why main() returns int

The entry point of a hosted C or C++ program is defined to return an integer status code. A value of 0 conventionally means success, and a non-zero value means some kind of failure or abnormal termination.

A minimal correct program looks like this:

c
1#include <stdio.h>
2
3int main(void) {
4    printf("Hello, world!\n");
5    return 0;
6}

The same principle applies in C++:

cpp
1#include <iostream>
2
3int main() {
4    std::cout << "Hello, world\n";
5    return 0;
6}

That exit code is how shells, scripts, CI systems, and parent processes decide whether your program completed successfully.

What 0 and non-zero mean

By convention:

  • '0 means success'
  • non-zero means failure or a specific error condition

For example:

c
1#include <stdio.h>
2
3int main(void) {
4    FILE *fp = fopen("missing.txt", "r");
5    if (fp == NULL) {
6        fprintf(stderr, "Could not open file\n");
7        return 1;
8    }
9
10    fclose(fp);
11    return 0;
12}

A shell script can then inspect the exit status after running the program. That is why returning meaningful codes matters more than it may first appear.

return 0; versus falling off the end

In modern C and C++, reaching the end of main() without an explicit return is equivalent to returning 0.

c
int main(void) {
    /* work */
}

This is valid, but many teams still prefer return 0; explicitly because it makes the success path obvious to readers. Whether you write it explicitly is a style choice. Returning a non-zero error code must always be explicit.

Use standard macros when they help readability

In C, <stdlib.h> defines EXIT_SUCCESS and EXIT_FAILURE.

c
1#include <stdio.h>
2#include <stdlib.h>
3
4int main(void) {
5    if (puts("ready") == EOF) {
6        return EXIT_FAILURE;
7    }
8    return EXIT_SUCCESS;
9}

These names can make intent clearer than raw numeric literals, especially for code that wants to emphasize success-versus-failure semantics rather than a specific custom code.

Custom error codes are often useful

For larger programs, non-zero should not just mean "something failed." Different values can represent different failure categories.

c
1#include <stdio.h>
2
3enum ExitCode {
4    EXIT_OK = 0,
5    EXIT_BAD_ARGUMENTS = 2,
6    EXIT_CONFIG_ERROR = 3
7};
8
9int main(int argc, char *argv[]) {
10    if (argc < 2) {
11        fprintf(stderr, "Usage: app <config>\n");
12        return EXIT_BAD_ARGUMENTS;
13    }
14
15    return EXIT_OK;
16}

That makes automation and debugging easier because callers can react differently to different failure modes.

What not to return

main() should not return void in standard hosted C or C++. Some compilers may accept void main() as an extension, but it is not the correct portable signature.

Valid common forms are:

  • 'int main(void) in C'
  • 'int main() in C++'
  • 'int main(int argc, char *argv[])'

Anything else should be treated with skepticism unless you are in a very specialized environment.

Common Pitfalls

  • Declaring void main() may compile on some toolchains but is not the correct portable standard form.
  • Returning 0 for failure cases makes shell scripts and automation think the program succeeded.
  • Using inconsistent custom error codes without documentation makes exit status harder to interpret.
  • Assuming the return value matters only to humans ignores how often build tools, scripts, and supervisors depend on it.
  • Forgetting that falling off the end of main() implies success can hide whether the success path was intentional or accidental.

Summary

  • In standard C and C++, main() should return int.
  • '0 means success, and non-zero means failure or a specific abnormal outcome.'
  • 'return 0; is explicit and clear, though falling off the end of main() also implies success.'
  • Use EXIT_SUCCESS, EXIT_FAILURE, or custom error codes when they improve clarity.
  • Avoid void main() if you want correct, portable code.

Course illustration
Course illustration

All Rights Reserved.