Is There C equivalent to Python's: if __name__ == '__main__': to write main() at the top of the file? [closed]
Asked Answered
D

5

6

In C writing function declarations before main seem redundant.

I don't want to use these methods:

  1. Write the functions in a different file then import on top.
  2. Write the whole function before main.
if __name__ == '__main__':
    main()

What is the C way of doing that?

#include <stdio.h>

void printHello(void);

int main(void)
{
    printHello();
}

void printHello(void)
{
    printf("Hello World\n");
}

The environment: I'm using a make script that uses clang with additional checks within Harvard's cs50 cloud IDE. The IDE was setup with c99 version of the language that don't compile without function declarations.

My tests: Using clang only still error the same; using GCC actually compiled with a warning only.

Why GCC worked? GCC saw a function call without a preceding declaration, it assumed the function returned int and compiled.(pre c99 behaviour)

Solved: The c99 definition eliminated implicit typing, so all functions must be declared before use. There is no equivalent for: if __name__ == '__main__': in C for the use of writing main() at the top of the file.

Thanks for your help John Bode; it makes sense now.

Decompound answered 26/7, 2019 at 10:43 Comment(6)
it's int main(<arguments>).Fumy
in this question you can see a bit more about main() function: #18928779Joey
??? That idiom is needed because python files are executed and sometimes you want them to act differently whether they are imported or not. C files are not executed. If you are asking whether it's better to put prototypes before the main function or use a header file, that's an opinion based question that's not a good fit for SO.Kathleenkathlene
Your two methods are equivalent.Groggy
There is no way to do that in C. There is no executable code outside functions, period. Unlike Python where there is nothing besides executable code.Cimah
"Also no need for functions declarations - it compiled ok." No, that just means that you're possibly entering the land of undefined behavior.Todhunter
C
0

You do need to make a forward declaration (if you want to keep main at start of file), as this code will be compiled and not executed. As the compiler compiles line by line, it won't know the signature of the function before reaching it.

People are used to develop more important functions at bottom of the file.

But how does compilation work ?

Compilation is in fact made in 2 steps.

1) Gcc (or whatever you use) will make a pre-compiled version of every file you have.

2) It links all those pre-compiled files into either, an executable, or a library file, etc...

Now that you know this, you can understand how it works:

  • At first step, the compiler can only know functions / variables that are present in a single file, but has no idea about the others, so if you call a function that's not in the file ==> he's not happy and generate an "undeclared function" error. But if you provide him with a header file, you basically tell the compiler "don't mind about this function missing, I'll add it later, in another file, at linking time". So the compilers ignores the error.
  • At second steps, when linking all files together, it will check once more, that you kept your promise, by giving him an implementation for the functions that were defined in your header files. Otherwise, you get another kind of error, like "could not find function XXX" (my error names aren't accurate, i haven't done C for a year now).
Chevrotain answered 26/7, 2019 at 11:6 Comment(2)
As long as the printHello function is in the same file as the main function, the main will know about it -- This is wrong. See my answer.Pharmaceutics
@Pharmaceutics yeah mb, I will edit my answer, I've done too many oop lately ^^Chevrotain
I
3

In C, the entry point of every program is the main function1, and there's no need to mark it specially - just define it as

int main( void ) { ... }

if you're not taking any command line arguments, or

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

if you are.

In C all functions must at least be declared before use. In older versions of C, if the compiler saw a function call without a preceding declaration, it assumed the function returned int. However, the 1999 version of the language definition eliminated implicit typing, so all functions must be declared before use.

A function definition counts as a declaration, and functions may be defined in any order within the source file. I always recommend that if they are all in the same translation unit2 that the called functions be defined before their callers, such as

#include <stdio.h>

int foo( int x ) { return 2 * x; }

int bar( int x ) { return foo( x ) * 3; }

int main( void )
{
  printf ( "bar( %d ) = %d\n" , 2, bar(2) );
  return 0;
}

This means your code reads "backwards" with main at the bottom, but IME this makes code easier to maintain, since you don't have to mess with separate declarations.

If a function is defined in a different translation unit (source file), then you will need a separate declaration. We usually do that by gathering those declarations in a separate header file, then #include-ing that file where necessary:

bar.h:

#ifndef BAR_H // include guard - not required, but good practice.
#define BAR_H // Keeps the contents of the file from being processed more than once in a translation unit

int foo( int ); // only need the type of the argument in a declaration

int bar( int );

#endif

bar.c:

#include "bar.h"

int foo( int x ) { return 2 * x; }

int bar( int x ) { return foo( x ) * 3; }

main.c

#include <stdio.h>
#include "bar.h"

int main( void )
{
  printf( "bar( %d ) = %d\n", 2, bar(2) );
  return 0;
}

How you partition functions into separate source and header files depends on the project.

You've likely noticed that I used angle brackets around stdio.h and quotes around bar.h. The different delimiters indicate different search paths to the compiler as to where to find the included file. Quotes mean to search the current working directory first, then other directories in the standard search path (indicated by angle brackets).


  1. In a hosted implementation, anyway. In a freestanding implementation, the entry point may be named something else.
  2. A translation unit is a source file after all preprocessing directives have been executed.

Inellineloquent answered 26/7, 2019 at 16:21 Comment(0)
P
1

The accepted answer contains a serious error. C compilers do not know about every top-level declaration in a file. They only know about the top-level declarations which appear textually above the declaration they are currently processing. It is easy to demonstrate this with data definitions:

// This code will not compile
const char *const strings[] = { sThis, sThat };
static const char sThis[] = "this";
static const char sThat[] = "that";

You will get hard errors for the above fragment because sThis and sThat are not yet available when the compiler is processing strings. Moving the definition of strings below the definition of sThis and sThat is the only way to fix the bug.

However, for functions, the legacy feature of "implicit function declaration" confuses the issue. In the default mode of most C compilers, this will compile, possibly with warnings:

#include <stdio.h>

int main(void)
{
    printHello();
}

void printHello(void)
{
    printf("Hello World\n");
}

because the compiler makes a guess about the type signature of printHello when it encounters it for the first time in a call expression. However, the guess is always wrong: an implicitly declared function is always understood to take an unspecified number of arguments and return int, which is literally never what you want. The compiler will cheerfully accept

#include <stdio.h>

int main(void)
{
    return printHello(1, "frobozz", 3.14159)
         + printHello(2.1828);
}

void printHello(void)
{
    printf("Hello World\n");
}

even though this is clearly nonsense.

The correct way to do what OP wants to do, in C, is with the "redundant" forward declarations that OP does not like:

#include <stdio.h>

static void printHello(void);

int main(void)
{
    printHello();
}

static void printHello(void)
{
    printf("Hello World\n");
}

This is the only way to communicate to the compiler that printHello takes no arguments and returns nothing, if you want to put the definition of printHello below the definition of main.

Pharmaceutics answered 26/7, 2019 at 13:29 Comment(0)
M
0

In C language, the first function called must have the following prototype :

int main(int argc, char* argv[])

Where argc is the number of arguments and argv[] is an array of char* containing the arguments
You can also declare the main the following if you don't matter the arguments :

int main()
Moorings answered 26/7, 2019 at 10:48 Comment(5)
You are wrong. The function main can be declared in C++ also like int main(). The int main( void ) is also a correct function declaration in C++. Though the type specifier void is redundant. In C this function declaration int main( void ) is a standard declaration.Pseudocarp
It depends on how you want to implement your code, I'll update the answerMoorings
@VladfromMoscow The void in int main(void) is not redundant in C. Nobody else brought up C++, I don't know why you did.Pharmaceutics
@Pharmaceutics Initially the question has the tag C++.:)Pseudocarp
See What should main() return in C and C++? for a complete discussion of correct signatures for main(). The first option is one valid option; the second is deprecated in C; it should be int main(void). It is fine in C++ where the rules are different — C and C++ are different languages.Wert
C
0

You do need to make a forward declaration (if you want to keep main at start of file), as this code will be compiled and not executed. As the compiler compiles line by line, it won't know the signature of the function before reaching it.

People are used to develop more important functions at bottom of the file.

But how does compilation work ?

Compilation is in fact made in 2 steps.

1) Gcc (or whatever you use) will make a pre-compiled version of every file you have.

2) It links all those pre-compiled files into either, an executable, or a library file, etc...

Now that you know this, you can understand how it works:

  • At first step, the compiler can only know functions / variables that are present in a single file, but has no idea about the others, so if you call a function that's not in the file ==> he's not happy and generate an "undeclared function" error. But if you provide him with a header file, you basically tell the compiler "don't mind about this function missing, I'll add it later, in another file, at linking time". So the compilers ignores the error.
  • At second steps, when linking all files together, it will check once more, that you kept your promise, by giving him an implementation for the functions that were defined in your header files. Otherwise, you get another kind of error, like "could not find function XXX" (my error names aren't accurate, i haven't done C for a year now).
Chevrotain answered 26/7, 2019 at 11:6 Comment(2)
As long as the printHello function is in the same file as the main function, the main will know about it -- This is wrong. See my answer.Pharmaceutics
@Pharmaceutics yeah mb, I will edit my answer, I've done too many oop lately ^^Chevrotain
T
0

A python file is also a python module. If you want to use something in the namespace of the module, you typically import it. The if __name__ == “__main__” construct is ordinarily used when, as is obvious, treating the module as executable (for testing and so on). With compiled languages like C, this is achieved by calling main in the .c file.

Truett answered 26/7, 2019 at 11:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.