-1

I have heard that calling int main(){...} was bad practice and one should rather call the function with its parameters int main(int argc, char* argv[]){...}, I was wondering if this could be generalized to function declarations in headers.

In some situations, one may have to write a function prototype in a header without any parameters on inputs (for some reasons of include troubles let say), and declare the input parameters and their types in the function definition in a distant .c file. Is this likely to cause security issues as one could make use of this absence of informations? Or is the function definition (with input parameters declared) preventing this? I couldn't find any link about this.

Binou
  • 124
  • 9
  • 1
    @Binou And you did well, because in C++ (at least), you cannot declare a function's protoype without any arguments and define it in the .cpp with arguments. These would not be the same functions at all, but an overload (and the second one would be private to the .cpp file, while the first one would miss a definition). – Fareanor Jan 14 '20 at 08:10
  • It's the compiler that determines valid forms of main(), never the programmer. As for what forms that are valid, see the linked duplicate. `int main()` is valid but obsolete style. `int main (void)` or with agc+argv are the strictly conforming forms. You cannot pass arbitrary parameters to `main()` without the compiler + OS calling convention allowing it. – Lundin Jan 14 '20 at 08:32
  • I don't understand the "closing as duplicate". I was asking about function declarations, not function calls. I talked about the main() call because I know about potential security issues and I was wondering in the other scenario. I already have a proper answer so it's fine but I don't see it as duplicate. – Binou Jan 14 '20 at 08:35

1 Answers1

2

In C when declaring a function prototype without any listed arguments, like in

voif my_function();  // No specified arguments

the compiler treats it as declaring a function with an unknown amount of arguments of unknown types.

That means callers could pass whatever arguments they like and the compiler would happily accept it, without any checking about correctness or not (since it's not possible). For the remainder of the translation unit, the arguments used for the first call will be assumed to be the arguments the function takes.

Now if another translation unit calls the same function with different arguments, you suddenly have mismatching calls. And if even one call doesn't match the actual arguments in the function definition then you will have undefined behavior.


This is of course different from defining a function without arguments:

void my_function()
{
    // Some code...
}

If the function haven't been otherwise declared yet, then this also declares the function as taking no arguments. This is in effect equivalent to

void my_function(void)
{
    // Some code...
}

Lastly for the main function. It's not allowed to declare a prototype of the main function, only to define (implement) it.

And int main(void) is a valid variant of the function, which (since a prototype isn't allowed) means that you can use int main() because it's equivalent to int main(void).

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • So if somebody calls the function with different parameters than those specified in the function *definition*, this wouldn't necessarily lead to a compilation error but rather to UB? – Binou Jan 14 '20 at 08:16
  • @Binou If the call and the definition is in different [translation units](https://en.wikipedia.org/wiki/Translation_unit_(programming)) the compiler simply can't check if the arguments match, and if they don't then yes you will have UB. – Some programmer dude Jan 14 '20 at 08:18