0

I wonder what happens when I play with the return value of the main function.

I found that if I return an array variable from main (which is supposed to be the exit status) and print the exit status in shell, the output is always 56. I wonder why?

The C program:

int* main(void) {
    static int x[3];
    x[0]=89;
    x[1]=15;
    x[2]=10;
    return x;
} 

I test it as follows:

gcc array_return.c -o array_return
./array_return
echo $?

The output is always 56 even if I change the size of the array, or change the numbers in it. What does the number 56 mean?

Ruslan Osmanov
  • 17,894
  • 7
  • 38
  • 53
  • 4
    56 doesn't mean anything; the program is invalid. – John Zwinck Oct 08 '16 at 13:57
  • 1
    @JohnZwinck I don't think so. If it was an error then why it won't change and stack at 56? Also my problem is nothing with returning the right thing at main (Everyones know 0 is correct). – İhsan Cemil Çiçek Oct 08 '16 at 14:00
  • 1
    Your program is invalid. 56 is not a useful number, it's just some random crap you ended up with because of some quirk of your platform. The valid type is int. If you enable compiler warnings as errors you may find your code as written won't even compile. For example my compiler says `error: return type of 'main' is not 'int'` – John Zwinck Oct 08 '16 at 14:01
  • @JohnZwinck my question is not duplicate. Do you job properly you might be right about 56 which I don't think so but my question not duplicate of any other question. I request you to unblock my question... – İhsan Cemil Çiçek Oct 08 '16 at 14:06
  • @JohnZwinck I can use char main return in my programs it return ASCII code so that it is not a crap. Also compilers are handwritten they are not gods program right? – İhsan Cemil Çiçek Oct 08 '16 at 14:07
  • 2
    OK, I will reopen this question and we will see how it goes. By the way, "Do your job properly" is stunning. You should try saying that to more people. – John Zwinck Oct 08 '16 at 14:08
  • @JohnZwinck my english is not native so do your job is not harsh in turkish. Sorry if I unplease you. – İhsan Cemil Çiçek Oct 08 '16 at 14:11
  • You should compile with `gcc -Wall -g`, improve your code till you get no warnings, then use the `gdb` debugger. BTW the C99 (or C11) standard consider your signature of `main` as invalid, you have some [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior) and that is awfully bad. – Basile Starynkevitch Oct 08 '16 at 15:41
  • @BasileStarynkevitch thanks for the -Wall -g args. I know main should always be int I just tried ^^ I use valgrind a lot btw that is nice too – İhsan Cemil Çiçek Oct 08 '16 at 20:25

2 Answers2

5

Your program returns a pointer. It's not an "array" as you put it in the question. Because the name of an array evaluates to the address of its first item (which is the same as address of the array itself).

In C, the value returned from the main function is interpreted as the exit status, i.e. the $? variable used in your example.

I guess, you're running Bash shell, since in Bash the exit status is stored in the $? variable. A pointer is usually a big number, at least bigger than 255, which is a maximum exit code in Bash:

Out of range exit values can result in unexpected exit codes. An exit value greater than 255 returns an exit code modulo 256. For example, exit 3809 gives an exit code of 225 (3809 % 256 = 225).

Now let's modify your program by printing the address of the variable, and the address modulo 256:

#include <stdio.h>

int main(void) {
    static int x[3];
    printf("%ld ==> %d\n", (size_t)x, (size_t)x % 256);
    return (int)x;
}

Let's compile it and test if I'm right:

$ gcc -Wall -g test.c -o test && ./test; echo $?
test.c: In function ‘main’:
test.c:6:12: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
     return (int)x;
            ^
6295620 ==> 68
68

As we can see, the return status is equal to 6295620 % 256, as it is documented in the official documentation.

Ruslan Osmanov
  • 17,894
  • 7
  • 38
  • 53
  • 1
    The one byte exit code is not a limitation of `bash` but a property of the kernel (see [execve(2)](http://man7.org/linux/man-pages/man2/execve.2.html), [_exit(2)](http://man7.org/linux/man-pages/man2/exit.2.html), [waitpid(2)](http://man7.org/linux/man-pages/man2/waitpid.2.html)...). Changing or patching the shell won't change that limit (exit codes being between 0 & 255) – Basile Starynkevitch Oct 08 '16 at 15:47
2

According to ISO C,int* main(void) is not one of the forms of the startup function main that an implementation is required to support. So the behavior is not defined by the language standard.

int *main(void) could work as a documented extension provided by your implementation of C. In this manner, C implementations can support additional ways of writing the startup function.

More probably, the construct is erroneous, and your implementation is simply ignoring the situation; it's just compiling the code and letting the machine instructions do what they may. To understand the actual behavior, you have to understand what is happening at that level.

Quite possibly, the bitwise representation of the returned pointer itself is interpreted as an integer termination status value, which translates to an operating system exit code of 56. (Perhaps some bitfield in the value, such as the lowest 8 bits, is 56). That's assuming that int * and int are returned from a function in the same way. They might not be. For instance, in C compilers for the Motorola 68000 series of processors there exists the convention that a pointer is returned via the A0 register, and an integer value in D0. So if an int * returning function is written to satisfy an external reference to something that is expected to return int, the caller receives whatever garbage happens to be in D0, while the pointer has gone into A0.

Because the behavior is not defined, there is no requirement for a diagnostic! In the C language, you can even write this:

int main[42] = { 3 };

in some environments that will compile, and link. When executed, the array data ends up used as a machine language function image. A program relying on this trick once (perhaps more than once) appeared in the IOCC: International Obfuscated C Contest.

Kaz
  • 48,579
  • 8
  • 85
  • 132