2

So I'm learning about functions in a book.

  1. It says we need to prototype or declare functions so the compiler can understand if they are correctly called or not.

But why does the main function works without a prototype?

  1. I used to write main functions in my learning process like this:

    int main(void)
    

    So it will not get any argument because of (void)

    I tried to run my program with argument for example > ./a.out 2

    int main(int y){ 
        printf("%s %d\n","y is",y); 
    } 
    

    When I run it normally y is 1, when run it with > ./a.out 1 y is 2, when there is more than one argument it increases by one. So it's not the right way but what causes this?

    Declaring y as char says nothing so my guess is it works like the return value of scanf(). It returns number of successful inputs.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
IMIEEET
  • 51
  • 7
  • 1
    I think [here contains](https://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c) some of your questions' answers, you can look. – Tuna Mar 31 '21 at 12:43
  • Ask the questions separately. When you ask several different questions at the same time, people knowing answers to only some of them might be reluctant to reply as they aren't able to provide the full answer. – choroba Mar 31 '21 at 12:43
  • Spend several days in reading [*Advanced Linux Programming*](https://mentorembedded.github.io/advancedlinuxprogramming/) and [syscalls(2)](https://man7.org/linux/man-pages/man2/syscalls.2.html). I guess you are using Linux. Like [GNU bash](https://www.gnu.org/software/bash/), the Linux [kernel](https://kernel.org/) is **free software** and you are allowed to download and study its source code – Basile Starynkevitch Mar 31 '21 at 13:13
  • @BasileStarynkevitch yeah im using linux. btw thanks for that book recommendation. seems like what i was looking for my last question – IMIEEET Mar 31 '21 at 14:18
  • Read documentation of [GCC](http://gcc.gnu.org/) and of [GDB](https://www.gnu.org/software/gdb/) then compile your C code with `gcc -Wall -Wextra -g` – Basile Starynkevitch Mar 31 '21 at 16:46

2 Answers2

3

A function must be either declared (i.e. a prototype) or defined before it is called. The main function is different from other functions in that it's called by the program startup code and not some other function.

There are however restrictions on what the signature of main can be. On a regular hosted implementation, the C standard says it can be either:

int main(void)

Or:

int main(int argc, char **argv)

The latter case is used to read command line arguments. argc contains the number of arguments passes, including the program name. argv contains the actual arguments as an array of char *.

Many systems also support:

int main(int argc, char **argv, char **envp)

Where envp contains the environment variables known to the program.

The prototype you're using: int main(int y) is not supported in any implementation I'm aware of, so attempting to use such a prototype for main invokes undefined behavior.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • thank you. but `argc` and `y` both works as number of arguments – IMIEEET Mar 31 '21 at 13:06
  • `main` being called by the startup code has nothing to do with whether a “prototype” is needed. (“Prototype” is the wrong term; the C standard defines this as a function declaration that includes the parameter types, in contrast to `()`. What is really at issue here is a function declaration.) In modern C, all function identifiers must be declared before they are used. `main` is declared in its definition and does not need any separate declaration because it is not usually otherwise used in the C source code of a program. If it is used, it needs a declaration, the same as any other identifier. – Eric Postpischil Mar 31 '21 at 13:06
  • @IMIEEET The name given to the arguments can be freely changed. The part that's important is the number and types of the arguments. – dbush Mar 31 '21 at 13:08
  • @IMIEEET: The standard declarations for `main` that the C standard provides are `int main(void)` and `int main(int, char **)`, where any parameter names can be filled in after the `int` and the `char **`. The names are irrelevant, but the specific forms are relevant: To match one of these forms, you must either have `void` or you must have two parameters, the first of type `int` and the second of type `char **`. `int main(int)` does not match one of those, so using it violates a rule in the C standard unless your implementation defines it. – Eric Postpischil Mar 31 '21 at 13:09
1

When I run it normally y is 1, when run it with > ./a.out 1 y is 2, when there is more than one argument it increases by one. So it's not the right way but what causes this?

The standard entry for program startup kind of answers both your questions:

N1570 § 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[]) { /* ... */ }

[...]

As dbush already stated in the accepted answer these are the only two main implementations allowed by the standard.

The standard leaves the responsability of dealing with undefined constructs opened and imposes no requirements for what the behavior should be, a given implementation may deal with the situation in any way it considers appropriate, this is known as undefined behavior.

What seems to be happening is that your compiler is assuming that y is argc, which is allowed (as you can see in the second snippet of highlighted citation above), and argc stores the number of arguments in the command line, which is consistent with the results you're having, but again, this behavior may differ in different compilers, systems or even versions of the same compiler.

anastaciu
  • 23,467
  • 7
  • 28
  • 53