-9

I have a program like this.

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

int main(int i) {                /* i will start from value 1 */
if(i<10)                        
printf("\n%d",main(++i));        /* printing the values until i becomes 9 */    
}

output : 
5
2
2
2

Can anyone explain how the output is coming ?? what main(++i) is returning for each iteration. Also it is producing output 5111 if i remove the \n in the printf function. Thanks in advance.

Sriraman
  • 7,658
  • 4
  • 40
  • 60
sree
  • 3
  • 2
  • @Jayesh calling `main` is legal in C. But `main` doesn't take one `int` parameter. – Yu Hao Aug 30 '14 at 05:53
  • `int main(i)` is not a valid function declaration. – Jayesh Bhoi Aug 30 '14 at 05:54
  • 1
    `i will start from value 1 i think` No it won't. `main()` is supposed to be `int main(int argc, char **argv)` and thats how it will be called by the system, you cannot make up whatever you want. Some compilers won't even accept this. – Havenard Aug 30 '14 at 05:55
  • 1
    Also, your `printf()` is printing the **return value of main()**, howover, your function `main()` doesn't return anything. Those numbers are memory garbage, undefined behaviour. – Havenard Aug 30 '14 at 05:59
  • @Havenard if main doesn't return a value, it return 0 by default. however in this case, calling main is UB anyway... – Bryan Chen Aug 30 '14 at 06:00
  • Seems to me it isn't setting a return value at all, thats why its printing `2`. 2 is the value returned by `printf()` after priting `\n5`. It is set to the register `EAX` by the first `printf()` call and reused by the others as the supposed return value of `main()`. – Havenard Aug 30 '14 at 06:03
  • 4
    Why are beginning C programmers so interested in how **really really bad** code works instead of learning to program well? – Jim Balter Aug 30 '14 at 06:23
  • My question is somewhat rhetorical. The nature of C encourages it, and teaching C as a beginning programming language is irresponsible. The opposite of this is http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/ ... people who get *that* sort of education create or join startups and become multimillionaires. People who learn C as a first language mostly go no further, and those who stay with C end up as grunts in corporate cubicles. – Jim Balter Aug 30 '14 at 07:21

6 Answers6

5

First of all, the declaration of main() is supposed to be int main(int argc, char **argv). You cannot modify that. Even if your code compiles, the system will call main() the way it is supposed to be called, with the first parameter being the number of parameters of your program (1 if no parameter is given). There is no guarantee it will always be 1. If you run your program with additional parameters, this number will increase.

Second, your printf() is attempting to print the return value of main(++i), howover, your main() simply don't return anything at all. You have to give your function a return value if you expect to see any coherence here.

And finally, you are not supposed to call your own program's entrypoint, much less play with recursion with it. Create a separate function for this stuff.

Havenard
  • 27,022
  • 5
  • 36
  • 62
  • 1
    "First of all, the declaration of main() is supposed to be int main(int argc, char **argv)." -- It doesn't have to be; the C standard explicitly allows `int main(void)`, as well as "some other implementation-defined manner". "with the first parameter being the number of parameters of your program" -- this is true if main is properly defined, but when defined way the OP did, there is no guarantee that `int i` will map to the first parameter passed by the system. " you are not supposed to call your own program's entrypoint" -- There's nothing in the C standard (vs. C++) that says you can't. – Jim Balter Aug 30 '14 at 06:36
  • @JimBalter Actually, using `int main(void)` you are only saying you don't care about the arguments. The system will still send them anyway, you just won't have any variable name associated with the stack addresses `EBP+8` (argc) and `EBP+12` (argv) (assuming 32-bits) to fetch them. – Havenard Aug 30 '14 at 16:35
  • You might try actually reading what I wrote: "when defined way the OP did" -- thats not `int main(void)`. "you are only saying you don't care about the arguments" -- duh. "The system will still send them anyway" -- duh. "you just won't have any variable name" -- the OP has a variable name ... `i`. Like I said, "there is no guarantee that int i will map to the first parameter passed by the system". Your comment doesn't address that (or anything else I wrote). – Jim Balter Aug 30 '14 at 17:29
  • Actually the calling convention guarantees that. – Havenard Aug 30 '14 at 18:05
  • Citation? Or to put it another way: you have no idea what you're talking about. It's bad enough that you are assuming a specific calling convention, with EBP+8 etc, when you don't even know what machine the OP is using. – Jim Balter Aug 30 '14 at 19:42
  • Because it doesn't metter. The calling convention guarantees this stuff. http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl Its either EBP+8 or RBP+16. And what are the chances he is using some exotic architecture? The guy can't even use `main()` properly. – Havenard Aug 31 '14 at 01:11
  • Your responses are not up to the standards of [C] at SO. That's the last I will say here. – Jim Balter Aug 31 '14 at 02:50
1

Here's what the C Draft Standard (N1570) says about main:

5.1.2.2.1 Program startup

1 The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

int main(void) { /* ... */ }

or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):

int main(int argc, char *argv[]) { /* ... */ }

or equivalent or in some other implementation-defined manner.

Clearly, the main function in your program is neither of the above forms. Unless your platform supports the form you are using, your program is exhibiting undefined behavior.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

This program has undefined behavior (UB) all over the place, and if you have a single instance undefined behavior in your program, you can't safely assume any output or behavior of your program - It legally can happen anything (although in real world the effects often are somewhat localized near the place of UB in the code. The old C90 standard listed are more than 100 (if i recall right) situations of UB and there is a not known number of UBs on top, which is behavior for situations, the standard do not describe. A set of situations, that are UB exists, for every C and C++ Standard.

In your case (without consulting standards) instances of UB are at least:

  • not returning an value of a function that is declared with a return value. (exception: calling main the FIRST time - thanks, Jim for the comments)
  • defining (and calling) main other than with the predefined forms of the standard, or as specified (as implementation defined behavior) by your compiler.

Since you have at least one instance of UB in your program, speculations about the results, are somewhat... speculative and must make assumptions about your compiler, your operating system, hardware, and even software running on parallel, that are normally not documented or can be known.

Community
  • 1
  • 1
Mark A.
  • 579
  • 4
  • 13
  • Calling `main` within a C program is **not** undefined behavior (C++ does disallow it but C does not). The standard even goes so far as to mention "the **initial** call to the main function" (emphasis added) in describing program termination. "not returning an value of a function that is declared with an return value" -- this is **not true** of `main` -- the C standard makes a special exception for it. – Jim Balter Aug 30 '14 at 06:45
  • @Jim Thanks, thats interesting. Is this exception in every incarnation of the C standards? Does it hold for every call or only for the initial one? – Mark A. Aug 30 '14 at 06:52
  • There are actually three specific sources of UB in the OP's code: the improper definition of `main`, the value of `i` in `i<10`, and the return value of `main(...)`. – Jim Balter Aug 30 '14 at 06:52
  • It's in every incarnation and only applies to the initial call: "If the return type of the main function is a type compatible with int, 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." -- At least, I *think* the return value of 0 only applies to the initial call ... the language is actually ambiguous, it seems to me. The OP's implementation certainly isn't acting as if `main` returns 0. – Jim Balter Aug 30 '14 at 06:54
  • @JimBalter Why is the value of ´i´ in the comparison undefined (more than by a error in main call)? – Mark A. Aug 30 '14 at 06:59
  • We have no idea what its value is when `main` is called by the system, so it's undefined the first time it is tested, and since it's undefined, so is `++i`, and so it's undefined for all subsequent tests as well. I suppose `++i` is also undefined behavior, but that would be of no consequence if the value weren't passed to `main` as its argument. – Jim Balter Aug 30 '14 at 07:05
  • "exception: calling main the FIRST time" -- More correctly, it's the return from the first call of `main` ... which *might never happen* because of all the UB ... on some systems this will recurse until it blows the stack. – Jim Balter Aug 30 '14 at 07:09
  • "calling main other than with the predefined forms of the standard" -- more accurately it's a matter of *defining* `main` with other than the predefined or implementation-specified forms ... of course the call must conform to the definition, but that's not the problem here. – Jim Balter Aug 30 '14 at 07:11
  • So there is no additional instance of UB for the counter on its own. It comes from the main call and return value. Both instances of UB are fixed (returning i, and calling main with the orignal argv) the progam will do fine. – Mark A. Aug 30 '14 at 07:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/60278/discussion-between-mark-a-and-jim-balter). – Mark A. Aug 30 '14 at 07:13
0

You are not initializing i, so by default value will be taken from the address where it is stored in RAM.

This code will produce garbage output if you run the code multiple times after restarting your computer.

The output will also depend on compiler.

prashant khunt
  • 154
  • 3
  • 8
  • The value of `i` is only relevant for the `i<10` test ... `main` doesn't return it so it has no bearing on what is printed. "This code will produce garbage output if you run the code multiple times after restarting your computer." -- Well, no, because memory is cleared before programs are run on all modern operating systems ... the results are quite deterministic, though unspecified. – Jim Balter Aug 30 '14 at 06:49
0

I'm surprised that even compiles.

When the operating system actually runs the program and main() gets called, two 32 (or 64) bit values are passed to it. You can either ignore them by declaring main(void), or use them by declaring main(int argc, char** args).

As the above prototype suggests, the first value passed is a count of the number of command-line arguments that are being passed to the process, and the second is a pointer to where a list of these arguments is stored in memory, likely on the program's local stack.

The value of argc is always at least 1, because the first item string in args is always the name of the program itself, generated by the OS.

Regarding your unexpected output, I'd say something is not getting pulled off or pushed onto the stack, so variables are getting mixed up. This is either due to the incomplete argument list for main() or the fact that you've declared main to return an int, but haven't returned anything.

  • "I'm surprised that even compiles." -- I don't get why people are surprised by this. The standard explicitly states that the implementation does not provide a prototype for `main`, so any definition is likely to compile unless the compiler goes out of the way to prevent it -- and the standard doesn't require that. Some compilers will give warnings, of course. – Jim Balter Aug 30 '14 at 06:39
-2

I think, the main method is calling itself inside the main method. to increment the value of a variable, i++ is printing the value of i before it increment while ++i it increment the value of i first before it print the value of i.

you could use this..

int x=0;
main()
{
   do
   {
   printf(x++);
   }while (i<10);

} 
  • 2
    *I think, the main method is calling itself inside the main method.* -- That much is obvious. *to increment the value of a variable, i++ is printing the value of i before it increment while ++i it increment the value of i first before it print the value of i.* -- this has no bearing on the question. And the value of `i`, pre- or post- incremented, is not being printed in the given code. *you could use this..* -- this is irrelevant. There is a specific question here, and you have done nothing to answer it. – Jim Balter Aug 30 '14 at 06:28