31
ceee
6y

So apparently calling the main() function inside the same main(), without a base case doesn't give an error in C 😑
Why ?!
Why the hell is it allowed ?!

Comments
  • 16
    Because why not? It's freedom™
  • 7
    @filthyranter
    Is this code allowed?
    I really want to run this code,but I left my laptop charger at college and the battery is dead 😐.
    The code was :

    #include<stdio.h>
    int main() {
    printf("%p",main());
    return 0;
    }
  • 17
    Because it's just a function like all other functions
  • 9
    @ceee Segmentation fault due to timeout.
  • 2
  • 5
    But that just means the OS ended it, so technically, yes, still allowed in C.
  • 3
    @filthyranter yeah but whats the point of allowinf it.
  • 19
    @ceee What's the point of restricting it? main is just a function, why overcomplicate a compiler?
  • 19
    Of course it doesn't give an error. Recursive functions are perfectly legal in C.
  • 20
    It is possible to do it and it is also possible to do it without getting a stack overflow from fucking around with the function stack in the same way we would with any other recursive function: terminating condition.

    Note: Proper C or C++ programs will include argument passing in the main function which can alter the course of a C/C++ program, such arguments can be used to activate a terminating condition.

    C and C++ are all about that I.O, is it so hard to imagine a process calling on your program passing certain inputs that would call the recursive function or not? Not for me although I would most definitely not do it that way.

    Remember, C will let you blow yourself up entirely :D and if I see someone else putting JS on the same level as c or cpp I will scream
  • 9
    Why disallow it?
    Because it sounds weird?

    C let's you do anything you want so long as it will produce valid assembly. Arbitrarily denying patterns is arbitrarily restricting options. It's also the compiler devs saying they know better than everyone else. That's a bad thing.
  • 2
    @Root Well the whole undefined behaviour around pointer aliasing is such a dark area of restrictions. Or the loads of other undefined behaviour that should have been made implementation defined, the most silly one the signed integer overflow.
  • 6
    Well the compiler just treats the main function as any other function, because it is not in any way special at the compile step. The main is only special to the C runtime and maybe the linker.

    Adding a special kind of function to the C compiler to prevent this would just add unecesaary complexity.
  • 1
    It's not weird. Like all the other comments, it's freedom in the way that main is a function and can be used recursively. Besides, putting some kind of restriction will add complexity in the compiler unnecessarily.

    Think that K&R was awesome programmers and their style was a reducionist one. That's the beauty of C (even Unix!!!).

    Please, don't call 'weird' before dive into the language culture/history/community.
  • 5
    For all who think this is normal, this type of behaviour is explicitly disallowed in the c++ standard. Any function can be called recursively except main.

    This is legal in C but it's a bad idea most of the time. You have to understand that C's philosophy was designed to have max flexibility in mind. It permits a lot of things that wouldn't be allowed in other languages.

    For example, in c++ you can't declare zero length arrays, but in c, you can declare an array with zero length. This makes no sense to allow but I've heard it's used in some very low level assembly cases.

    There's probably a very niche requirement somewhere for some esoteric piece of software to call main recursively so they mustve left that feature in. That's how the C spec is designed. Unless doing that action is 100% unallowable, they don't care about it. For most quirks, they leave it to the intelligence of the programmer to use the features safely.
  • 6
    @hashedram of course (extern) zero length arrays make sense, I'm using that all the time for compile time assertions e.g. about data sizes. If everything is OK, the external array is declared with zero length, and the compiler will throw it away. If things go wrong, they are declared with negative size, and compilation will abort. Cute trick from the Linux kernel.
  • 2
    @hashedram gcc still allows it tho and only gives you a warning if you compile with -Wpedantic.
  • 9
    And btw, not being able to call main from anywhere sucks especially for embedded. I need to call main() from the reset exception after I have manually set up the environment as the C standard expects it to be upon entry of main(). Low level? Eh, yeah, but that's what C is for.
  • 4
    C wouldn't be what it is if it didn't allow this and similar shenanigans. The ability to do this shit and pretty much anything else you want is why I love C.
  • 3
    @Fast-Nop wow I didn't think of this. Makes sense now.
  • 3
    @Fast-Nop yes. C allows hacky things like that even if a feature doesn't make immediate sense normally.
  • 5
    Just a note why that hack with the zero / negative array size is useful. What I actually would want is this:

    #if (sizeof(T_FOO) > MAX_FOO_SIZE)

    #error "foo type too large."

    #endif

    That fails because #if is preprocessor, but sizeof is only available in the compile stage, i.e. after the preprocessor has already finished. So that needs a workaround, in some global header file:

    #define STATIC_ASSERT(condition,assertlabel,message) extern int assertlabel[!!(condition)-1];

    And then in the C files, you can use it like this:

    STATIC_ASSERT((sizeof(T_FOO) <= MAX_FOO_SIZE),assert_foo_type,"foo type too large.");

    Works with all conditions that can be determined during compile time.
Add Comment