2

I saw a special definition of main() function, and I don't know how it is defined in this way? I haven't seen this style before.

main (m1,s) char *s; 
{
}

I don't understand this way of defining a function.

Complete code

#include "stdio.h"
#define e 3
#define g (e/e)
#define h ((g+e)/2)
#define f (e-g-h)
#define j (e*e-g)
#define k (j-h)
#define l(x) tab2[x]/h
#define m(n,a) ((n&(a))==(a)) //if n==a then the m(n,a)==1 else m(n,a)==0

long tab1[]={ 989L, 5L, 26L, 0L, 88319L, 123L, 0L, 9367L }; //L means It is a long integer literal.
int tab2[] = { 4,6,10,14,22,26,34,38,46,58,62,74,82,86};
main (m1,s) char *s; {
    int a,b,c,d,o[k],n = (int)s;
    if (m1==1){char b[2*j+f-g]; main (l(h+e)+h+e,b); printf(b);}
    else switch (m1-=h){
        case f:
            a = (b=(c=(d=g)<<g)<<g)<<g;
            return(m(n,a|c)|m(n,b)|m(n,a|d)|m(n,c|d));
        case h:
            for (a=f;a<j;++a)if(tab1[a]&&!(tab1[a]%((long)l(n))))return(a);
        case g:
            if(n<h)return(g);
            if (n<j){n-=g;c='D';o[f]=h;o[g]=f;}
            else {c='\r'-'\b';n-=j-g;o[f]=o[g]=g;}
            if ((b=n)>=e)for (b=g<<g;b<n;++b)o[b]=o[b-h]+o[b-g]+c;
            return (o[b-g]%n+k-h);
        default:
            if (m1-=e) main (m1-g+e+h, s+g); else * (s+g)=f;
            for (*s=a=f; a<e;) *s=(*s<<e)|main(h+a++,(char *)m1);
    }
    }
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • 1
    Hint: if this code comes from your learning material, you should throw it away. The code is unreadable and full of bad practice. – Jabberwocky Apr 14 '23 at 09:26
  • Possible duplicate of [Alternative (K&R) C syntax for function declaration versus prototypes](https://stackoverflow.com/questions/1630631/alternative-kr-c-syntax-for-function-declaration-versus-prototypes) – PC Luddite Apr 14 '23 at 09:32
  • 2
    Is this from the [IOCCC](https://www.ioccc.org/)? I'm not being sarcastic, it genuinely looks like it is, with recursive main() calls and all. Or maybe it's "code golf". Obfuscation is borderline off-topic here. – Lundin Apr 14 '23 at 09:44
  • 1
    The output of this code is "Hello World!", yes I think is a code golf. – amir mardani Apr 14 '23 at 09:52
  • @PCLuddite No. The linked question only talks about K&C Style function prototypes. This question is also about the unusual `char *` instead of `char **` parameter. – 12431234123412341234123 Apr 14 '23 at 10:26

1 Answers1

4

This is K&R C Style. Which predates ANSI and ISO C89.

K&R C (and C89) uses implicit int, if a type is not given int is implied, so in your example m1 has the type int. In K&R C the types of the parameter are given after, in your case the parameter s is declared as char *. The implicit int is also used for the return type, so if a function definition has no return type is given, it is int, like it does for your main function.

That gives you the prototype int main(int m1, char *s); for your main() function. However, main() normally, in hosted environments, expects either no parameters (int main (void);) or a int with an array of pointers to char or equivalent (int main (int, char **);). POSIX also accept int main (int, char **, char **);. Most freestanding environments normally expect either int main(void); or void main(void);. Your prototype does not fit any of this (nor any other ones i know of), and seems wrong. Where is it used?

See also: Alternative (K&R) C syntax for function declaration versus prototypes

Edit

After seeing that it is from obfuscated code, that just prints "hallo world!\n", and doesn't accept arguments: The prototype int main(int m1, char *s); for main is not standard in ISO C or any other C environment i know. And the program breaks when you pass too many arguments. However, when no argument is given, the char *s parameter is only used when called from within the program, and then the type char * works. This isn't good practice (quite the opposite, but i guess that was the goal).

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • Hello, thank you for your answer. I added the complete code, the output of this code is just: "Hello World!". – amir mardani Apr 14 '23 at 09:12
  • I was more interested from where you got that code. But now it looks like some kind of code made with Obfuscation, which explains why this style is used. – 12431234123412341234123 Apr 14 '23 at 10:27
  • *That gives you the prototype `int main(int m1, char *s);` for your `main()` function.* It's important to note that K&R-style functions **do not have prototypes**, and that means arguments passed to K&R-style functions undergo [default argument promotions](https://stackoverflow.com/questions/1255775/default-argument-promotions-in-c-function-calls). That mismatch is probably why you noted the program breaking when passed too many arguments - the host environment uses a standard `main()` with a prototype and passes a `char **argv` value that gets interpreted as a simple `char *`. – Andrew Henle Apr 14 '23 at 19:14