Casting main() not allowed?

B

ballpointpenthief

Have a look at this

#include <stdio.h>
#include <string.h>
int track = 0;
char this[10] = "why ";
char that[10] = "not?";
int main(void)
{
track++;
if (track < 5)
main();
if (track == 5)
{
strcat(this,(char *)main());
printf("%s\n", this);
}
if (track == 6)
{
track = 7;
return (int)that;
}
if (track == 7) return 0;
return 0;
}

I'm not really sure what my question is, but I'm quite suprised it
works.
Any other ridiculous things you can do with a recursive main?

Matt
 
A

Andrew Poelstra

ballpointpenthief said:
Have a look at this

#include <stdio.h>
#include <string.h>
int track = 0;
char this[10] = "why ";
char that[10] = "not?";
int main(void)
{
track++;
if (track < 5)
main();
if (track == 5)
{
strcat(this,(char *)main());
printf("%s\n", this);
}
if (track == 6)
{
track = 7;
return (int)that;
}
if (track == 7) return 0;
return 0;
}

I'm not really sure what my question is, but I'm quite suprised it
works.
Any other ridiculous things you can do with a recursive main?

Matt
That looks like it's good with any recursive function. main() is no
different than any other function, except that its first caller is the OS.
 
K

Keith Thompson

ballpointpenthief said:
Have a look at this
[...]
int main(void)
{ [...]
strcat(this,(char *)main()); [...]
return 0;
}

I'm not really sure what my question is, but I'm quite suprised it
works.

What do you mean when you say it "works"?

main is a function that returns an int. You've declared it so it
takes no arguments, so main() is a valid call; since the only value it
returns is 0, the expression main() evaluates to the int value 0.

You then cast this value to type char*. This is allowed, but
non-portable; the result of converting an integer to a pointer is
implementation-defined. Converting an integer *constant* 0 to a
pointer type yields a null pointer. Converting a non-constant integer
expression with a value of 0 to a pointer type is very likely to yield
a null pointer, but it's not required to (though there's some
disagreement on this point).

So, you're calling strcat() with what is most likely null pointer as
its second argument. The result is undefined behavior, which is a
common result of using pointer casts without being *very* careful.
Casting typically tells the compiler to shut up and stop complaining,
so the lack of a warning message (assuming you didn't get one) isn't
surprising.
Any other ridiculous things you can do with a recursive
main?

There are infinitely many bad C programs that can be written. Alas,
too many of them actually exist; I'm afraid I don't have time to
enumerate all the others.
 
F

Flash Gordon

ballpointpenthief said:
Have a look at this

#include <stdio.h>
#include <string.h>
int track = 0;
char this[10] = "why ";
char that[10] = "not?";
int main(void)
{
track++;
if (track < 5)
main();
if (track == 5)
{
strcat(this,(char *)main());

This will work assuming that the int value is a valid int representation
of a pointer.
printf("%s\n", this);
}
if (track == 6)
{
track = 7;
return (int)that;

This will work provided that the pointer converted to an int actually
fits. For a while, this has been the case on most popular
implementations, but with 64 bit systems this is quite likely not to
work. Pointers are 64 bits but ints are only 32 bits, so what do you
think will happen to the other 32 bits?
}
if (track == 7) return 0;
return 0;
}

I'm not really sure what my question is, but I'm quite suprised it
works.

Keep trying other systems and you will find conforming implementations
where it does not work.
Any other ridiculous things you can do with a recursive main?

Lots, However, I would not recommend any of them. The real challenge is
to find a sensible use for calling main recursively!
 
B

ballpointpenthief

Keith said:
You then cast this value to type char*. This is allowed, but
non-portable; the result of converting an integer to a pointer is
implementation-defined.
So, you're calling strcat() with what is most likely null pointer as
its second argument. The result is undefined behavior....
<snip>

I think you must have skimmed the line...
return (int)that;
Where I am returning a pointer converted to an integer. (Although I'm
not sure whether this would neccesarily fit in an int.)
Is that portable?
 
R

Richard Tobin

ballpointpenthief said:
I think you must have skimmed the line...
return (int)that;
Where I am returning a pointer converted to an integer. (Although I'm
not sure whether this would neccesarily fit in an int.)
Is that portable?

No.

It will typically work if int is "big enough" (which it often isn't on
modern systems), but even that is not guaranteed.

C99 provides an intptr_t integer type through which pointers can be
passed, but unfortunately it's optional.

-- Richard
 
K

Keith Thompson

ballpointpenthief said:
<snip>

I think you must have skimmed the line...
return (int)that;
Where I am returning a pointer converted to an integer. (Although I'm
not sure whether this would neccesarily fit in an int.)
Is that portable?

Yes, I did miss that line. I also didn't take the time figure out the
program's control flow.

C99 6.3.2.3 p5-6:

An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined, might
not be correctly aligned, might not point to an entity of the
referenced type, and might be a trap representation.

Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type, the behavior is
undefined. The result need not be in the range of values of any
integer type.
 
P

Peter Nilsson

Richard said:
...
C99 provides an intptr_t integer type through which pointers can be
passed, but unfortunately it's optional.

Why 'unfortunately'? I have to wonder why it exists at all in C99!
 
R

Richard Bos

ballpointpenthief said:
<snip>

I think you must have skimmed the line...
return (int)that;
Where I am returning a pointer converted to an integer. (Although I'm
not sure whether this would neccesarily fit in an int.)
Is that portable?

Not only is it not portable, it is a very silly idea. Why on earth would
you want to torture main() so? What has it ever done to you?

Richard
 
A

ais523

Flash said:
ballpointpenthief wrote:


Lots, However, I would not recommend any of them. The real challenge is
to find a sensible use for calling main recursively!

I was once writing a bytecode interpreter, where one of the legal
commands meant 'replace the currently running program with this string,
and run the string as if it were a program, with the command-line
arguments shifted left.' I implemented this with a static variable
holding the program, and when this command was reached it copied the
string into the program, and then executed something like
return main(argc-1, argv+1);
Of course, this could just be replaced by a loop, but it was not a
command that was frequently run (except by a bootstrap that always ran)
and I didn't want to special-case it in the startup code. (The static
variable initially held the bootstrap, and the bootstrap loaded the
file in argv[1] and ran it with that command. As a result, argv[1]
shifted onto argv[0] as a bonus, as it gave the filename of the program
now running). For a compiler that optimizes tail-recursion, this isn't
even very inefficient (a function calling itself in a 'return'
statement must be a good candidate for tail-recursion elimination!).
 
F

Flash Gordon

ais523 said:
I was once writing a bytecode interpreter, where one of the legal
commands meant 'replace the currently running program with this string,

<snip>

You spoilt the challenge for the OP! I didn't say one couldn't find a
sensible use for it, just indicated it was a challenge.
 
A

ais523

Flash said:
<snip>

You spoilt the challenge for the OP! I didn't say one couldn't find a
sensible use for it, just indicated it was a challenge.

I'm not entirely sure whether that last post was meant to be serious or
not. If it was, I apologize. If the challenge was intended purely for
the OP and you had stated so, I of course would not have tried to
answer it here.
 
F

Flash Gordon

ais523 said:
I'm not entirely sure whether that last post was meant to be serious or
not. If it was, I apologize. If the challenge was intended purely for
the OP and you had stated so, I of course would not have tried to
answer it here.

Nothing to apologise for, I was at most half serious. I was also amused
because it was scripting that I was thinking of as a possible reasonable
use for a recursive call to main. Anyway, any post to a group is open to
comment from all.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc

Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,183
Messages
2,570,964
Members
47,511
Latest member
svareza

Latest Threads

Top