Is there any difference between return n and exit(n) in C?

Is there any difference between return n (in the main function) and exit(n) in C? Is it defined by C or POSIX standards or it depends on OS or compiler?

0

In most cases, there’s no difference, but here’s a C program that’s likely to behave differently depending on whether it uses return 0; or exit(0);:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>#include <stdio.h>
#include <stdlib.h>
static char *message;
void cleanup(void) {
printf("message = "%s"n", message);
}
int main(void) {
char local_message[] = "hello, world";
message = local_message;
atexit(cleanup);
#ifdef USE_EXIT
puts("exit(0);");
exit(0);
#else
puts("return 0;");
return 0;
#endif
}
</code>
<code>#include <stdio.h> #include <stdlib.h> static char *message; void cleanup(void) { printf("message = "%s"n", message); } int main(void) { char local_message[] = "hello, world"; message = local_message; atexit(cleanup); #ifdef USE_EXIT puts("exit(0);"); exit(0); #else puts("return 0;"); return 0; #endif } </code>
#include <stdio.h>
#include <stdlib.h>

static char *message;

void cleanup(void) {
    printf("message = "%s"n", message);
}

int main(void) {
    char local_message[] = "hello, world";
    message = local_message;
    atexit(cleanup);
#ifdef USE_EXIT
    puts("exit(0);");
    exit(0);
#else
    puts("return 0;");
    return 0;
#endif
}

Because of the atexit() call, either exit(0); or return 0; causes the cleanup function to be invoked. The difference is that if the program calls exit(0);, the cleanup happens while the “call” to main() is still active, so the local_message object still exists. Executing return 0;, however, immediately terminates the invocation of main() and then invokes the cleanup() function. Since cleanup() refers (via the global message pointer) to an object that’s allocated locally to main, and that object no longer exists, the behavior is undefined.

Here’s the behavior I see on my system:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>$ gcc -DUSE_EXIT c.c -o c && ./c
exit(0);
message = "hello, world"
$ gcc c.c -o c && ./c
return 0;
message = ""
$
</code>
<code>$ gcc -DUSE_EXIT c.c -o c && ./c exit(0); message = "hello, world" $ gcc c.c -o c && ./c return 0; message = "" $ </code>
$ gcc -DUSE_EXIT c.c -o c && ./c
exit(0);
message = "hello, world"
$ gcc c.c -o c && ./c
return 0;
message = ""
$ 

Running the program without -DUSE_EXIT could do anything, including crashing or printing "hello, world" (if the memory used by local_message happens not to be clobbered).

In practice, though, this difference only shows up if objects defined locally inside main() are made visible outside main() by saving pointers to them. This could plausibly happen for argv. (Experiment on my system shows that the objects pointed to by argv and by *argv continue to exist after returning from main(), but you shouldn’t depend on that.)

  • For C
    The Standard says that a return from the initial call to main is equivalent to calling exit. However, a return from main cannot be expected to work if data local to main might be needed during cleanup.

  • For C++

When exit(0) is used to exit from program, destructors for locally scoped non-static objects are not called. But destructors are called if return 0 is used.

Program 1 – – uses exit(0) to exit

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class Test {
public:
Test() {
printf("Inside Test's Constructorn");
}
~Test(){
printf("Inside Test's Destructor");
getchar();
}
};
int main() {
Test t1;
// using exit(0) to exit from main
exit(0);
}
</code>
<code>#include<iostream> #include<stdio.h> #include<stdlib.h> using namespace std; class Test { public: Test() { printf("Inside Test's Constructorn"); } ~Test(){ printf("Inside Test's Destructor"); getchar(); } }; int main() { Test t1; // using exit(0) to exit from main exit(0); } </code>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>

using namespace std;

class Test {
public:
  Test() {
    printf("Inside Test's Constructorn");
  }

  ~Test(){
    printf("Inside Test's Destructor");
    getchar();
  }
};

int main() {
  Test t1;

  // using exit(0) to exit from main
  exit(0);
}

Output:
Inside Test’s Constructor

Program 2 – uses return 0 to exit

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class Test {
public:
Test() {
printf("Inside Test's Constructorn");
}
~Test(){
printf("Inside Test's Destructor");
}
};
int main() {
Test t1;
// using return 0 to exit from main
return 0;
}
</code>
<code>#include<iostream> #include<stdio.h> #include<stdlib.h> using namespace std; class Test { public: Test() { printf("Inside Test's Constructorn"); } ~Test(){ printf("Inside Test's Destructor"); } }; int main() { Test t1; // using return 0 to exit from main return 0; } </code>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>

using namespace std;

class Test {
public:
  Test() {
    printf("Inside Test's Constructorn");
  }

  ~Test(){
    printf("Inside Test's Destructor");
  }
};

int main() {
  Test t1;

   // using return 0 to exit from main
  return 0;
}

Output:
Inside Test’s Constructor
Inside Test’s Destructor

Calling destructors is sometimes important, for example, if destructor has code to release resources like closing files.

Note that static objects will be cleaned up even if we call exit(). For example, see following program.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class Test {
public:
Test() {
printf("Inside Test's Constructorn");
}
~Test(){
printf("Inside Test's Destructor");
getchar();
}
};
int main() {
static Test t1; // Note that t1 is static
exit(0);
}
</code>
<code>#include<iostream> #include<stdio.h> #include<stdlib.h> using namespace std; class Test { public: Test() { printf("Inside Test's Constructorn"); } ~Test(){ printf("Inside Test's Destructor"); getchar(); } }; int main() { static Test t1; // Note that t1 is static exit(0); } </code>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>

using namespace std;

class Test {
public:
  Test() {
    printf("Inside Test's Constructorn");
  }

  ~Test(){
    printf("Inside Test's Destructor");
    getchar();
  }
};

int main() {
  static Test t1;  // Note that t1 is static

  exit(0);
}

Output:
Inside Test’s Constructor
Inside Test’s Destructor

5

Its worth noting that C standard (C99) defines two types of execution environments, Freestanding Environment and Hosted Environment. Freestanding environment is a C environment which does not support the C libraries and is intended for embedded applications and the like. A C environment which supports the C libraries is called a Hosted environment.

C99 says, in a Freestanding environment program termination is implementation defined. So, if the implementation defines main, return n, and exit, their behaviors are as is defined in that implementation.

C99 defines Hosted environment behavior as,

If the return type of the main function is a type compatible with it, a return from the
initial call to the main function is equivalent to calling the exit function with the value
returned by the main function as its argument; reaching the } that terminates the main
function returns a value of 0. If the return type is not compatible with int, the
termination status returned to the host environment is unspecified.

1

From the C standard’s perspective, not really, other than return being a statement and exit() being a function. Either will cause any functions registered with atexit() to be called followed by termination of the program.

There are a couple of situations you want to watch out for:

  • Recursion in main(). While rarely seen in practice, it is legal in C. (C++ explicitly forbids it.)
  • Re-use of main(). Sometimes an existing main() will be renamed something else and be called by a new main().

The use of exit() will introduce a bug if either of those happens after you’ve written the code, especially if not terminating abnormally. To avoid that, it’s a good idea to be in the habit of treating main() as the function it is and using return when you want it to end.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật