Valhalla Legends Forums Archive | C/C++ Programming | Better than recursing on main - for Mephisto

AuthorMessageTime
iago
I wrote some code that acts similarely to recursing over main, except without the messy call stack. It runs on my x86 slackware 9.1 install, and I won't guarentee it'll work anywhere else:

[code]#include <stdio.h>
int i;
int main(int argc, char **argv)
{
int buffer[argc];

printf("%d\t", i++);

if(i < 100)
buffer[7] -= 5;

return 0;
}
[/code]

*grin*

<edit> sample output:
[code]iago@laptop:~/Projects/C$ gcc test.cpp ; a.out
0 1 2 3 4 5 6 7 8 9 10   
11 12 13 14 15 16 17 18 19 20
21    22 23 24 25 26 27 28 29 30
31 32    33 34 35 36 37 38 39 40
41 42 43    44 45 46 47 48 49 50
51 52 53 54    55 56 57 58 59 60
61 62 63 64 65    66 67 68 69 70
71 72 73 74 75 76    77 78 79 80
81 82 83 84 85 86 87    88 89 90
91 92 93 94 95 96 97 98   99 iago@laptop:~/Projects/C$
[/code]
April 26, 2004, 8:15 PM
Myndfyr
How does this work iago? Does it reposition the instruction register so that the code points back to the printf instruction? Because there is no loop...
April 26, 2004, 9:02 PM
Adron
[quote author=iago link=board=30;threadid=6491;start=0#msg57034 date=1083010559]
[code]#include <stio.h>
int i;
int main(int argc, char **argv)
{
int buffer[argc];

printf("%d\t", i++);

if(i < 100)
buffer[7] -= 5;

return 0;
}
[/code]

*grin*
[/quote]

[code]#include <stdio.h>[/code]

It's interesting code, but I don't quite understand the point of having argc in "buffer[argc]". To be honest, I don't understand how you can pass a variable as the size argument to an auto array. I was expecting a compilation error there, but it compiled just fine. The program runs ok too, but prints rather much on stderr while running.
April 26, 2004, 9:16 PM
iago
Now that you mention it, I don't know either. I used argc simply to confuse the guy at work I was showing it to :)

Myndfyre - it repositions its return address to the "call" instruction.
April 26, 2004, 9:27 PM
Mephisto
stdio? :p
April 26, 2004, 10:54 PM
iago
[quote author=Mephisto link=board=30;threadid=6491;start=0#msg57045 date=1083020054]
stdio? :p
[/quote]

bah, typo.. I deleted some global variables I stopped using and had to retype the include :P
April 26, 2004, 10:59 PM
Arta
[quote author=Adron link=board=30;threadid=6491;start=0#msg57042 date=1083014191]
It's interesting code, but I don't quite understand the point of having argc in "buffer[argc]". To be honest, I don't understand how you can pass a variable as the size argument to an auto array. I was expecting a compilation error there, but it compiled just fine. The program runs ok too, but prints rather much on stderr while running.
[/quote]

It does when I compile it (under windows). I don't understand this either!
April 27, 2004, 1:36 PM
Mephisto
I thought you could only use a constant value/expression when declaring arrays...At least according to what I was taught you can't use a variable to declare an array in the subscript, because a variables *varies* and the compiler needs to know exactly how much to allocate for the array.

Edit: Apparantly you can declare an array with a variable in the subscript...It makes sense to me too... :p I never tested it, but should've, so I wrote this very simple program. ;)

[code]
int main() {
int x = 5;
int array[x];
return 0;
}[/code]
April 27, 2004, 2:13 PM
iago
[quote author=Mephisto link=board=30;threadid=6491;start=0#msg57089 date=1083075199]
I thought you could only use a constant value/expression when declaring arrays...
[/quote]
Perhaps argc/argv are special? I have no idea why it works :)


Here's something else interesting that I noticed:
[code]int main()
{
main();
return 0;
}
[/code]
This will not compile on Linux. I get the error:
[code]iago@laptop:~/Projects/C$ gcc -Wall test2.cpp
/tmp/cc8BvbGZ.o(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
collect2: ld returned 1 exit status
iago@laptop:~/Projects/C$[/code]
April 27, 2004, 2:18 PM
iago
[quote author=Mephisto link=board=30;threadid=6491;start=0#msg57089 date=1083075199]
I thought you could only use a constant value/expression when declaring arrays...At least according to what I was taught you can't use a variable to declare an array in the subscript, because a variables *varies* and the compiler needs to know exactly how much to allocate for the array.

Edit: Apparantly you can declare an array with a variable in the subscript...It makes sense to me too... :p I never tested it, but should've, so I wrote this very simple program. ;)

[code]
int main() {
int x = 5;
int array[x];
return 0;
}[/code]
[/quote]

Did you try running that with warnings?

I get this:
[code]iago@laptop:~/Projects/C$ gcc -Wall test2.cpp
test2.cpp: In function `int main()':
test2.cpp:4: warning: unused variable `int array[((x - 1) + 1)]'
iago@laptop:~/Projects/C$[/code]

it declares that variable "array" very weirdly :/

<edit>
I tried it on c, not c++, and it still works
[code]iago@laptop:~/Projects/C$ gcc -Wall test.c
test.c: In function `main':
test.c:4: warning: unused variable `array'
iago@laptop:~/Projects/C$[/code]

Ouch, my brain :(
April 27, 2004, 2:20 PM
iago
In case somebody's curious, this program:

[code]#include <stdio.h>

int main()
{
int x;

printf("What is the value of x?\n");
scanf("%d", &x);

int array[x];

for(int i = 0; i < x; i++)
{
array[i] = 0;
}

return 0;
}
[/code]

compiles fine, on Linux, and produces the main function:

[code]main:
.LFB1:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
subl $24, %esp
.LCFI2:
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl %esp, -12(%ebp)
subl $12, %esp
pushl $.LC0
.LCFI3:
call printf
addl $16, %esp
subl $8, %esp
leal -4(%ebp), %eax
pushl %eax
pushl $.LC1
call scanf
addl $16, %esp
movl -4(%ebp), %eax
decl %eax
sall $2, %eax
addl $4, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
subl %eax, %esp
movl %esp, -16(%ebp)
movl $0, -8(%ebp)
.L2:
movl -8(%ebp), %eax
cmpl -4(%ebp), %eax
jl .L5
jmp .L3
.L5:
movl -8(%ebp), %eax
movl -16(%ebp), %edx
movl $0, (%edx,%eax,4)
leal -8(%ebp), %eax
incl (%eax)
jmp .L2
.L3:
movl -12(%ebp), %esp
movl $0, %eax
leave
ret
[/code]

I don't have time right now to figure out how this is working, but feel free :)
April 27, 2004, 2:28 PM
Yoni
Btw, has anyone tried compiling with ANSI-compliance enabled?
I'm pretty sure this is a GCC extension.
Edit: I checked (Comeau) and it's standard C99. Interesting...

As for how it works...

[quote author=iago link=board=30;threadid=6491;start=0#msg57095 date=1083076103]
[code] subl %eax, %esp
[/code]
[/quote]
April 27, 2004, 3:10 PM
iago
[quote author=Yoni link=board=30;threadid=6491;start=0#msg57101 date=1083078640]
Btw, has anyone tried compiling with ANSI-compliance enabled?
I'm pretty sure this is a GCC extension.
Edit: I checked (Comeau) and it's standard C99. Interesting...

As for how it works...

[quote author=iago link=board=30;threadid=6491;start=0#msg57095 date=1083076103]
[code] subl %eax, %esp
[/code]
[/quote]
[/quote]

Wow,that's smart, it subtracts the variable from esp :) *impressed*

[code]iago@laptop:~/Projects/C$ gcc -ansi -fno-nonansi-builtins -Wall test2.cpp
iago@laptop:~/Projects/C$[/code]

works fine :)

<edit> I think -ansi means standard C89.

I had no idea this was allowed. hmm.
April 27, 2004, 3:26 PM
Arta
Well, I copied your code straight over:

[code]
error C2466: cannot allocate an array of constant size 0
error C2057: expected constant expression
error C2133: 'buffer' : unknown size
[/code]

Although I think I see how it works now.. Kind've intentionally overflowing the stack - clever :)
April 27, 2004, 7:21 PM
iago
[quote author=Arta[vL] link=board=30;threadid=6491;start=0#msg57119 date=1083093675]
Well, I copied your code straight over:

[code]
error C2466: cannot allocate an array of constant size 0
error C2057: expected constant expression
error C2133: 'buffer' : unknown size
[/code]

Although I think I see how it works now.. Kind've intentionally overflowing the stack - clever :)
[/quote]

Try making my array a constant size of "1"
April 27, 2004, 8:22 PM
Mephisto
Arta, do you get that error when you try to declare an array with a non-constant value/expression?
April 27, 2004, 9:02 PM
kamakazie
[quote author=iago link=board=30;threadid=6491;start=0#msg57092 date=1083075492]
[quote author=Mephisto link=board=30;threadid=6491;start=0#msg57089 date=1083075199]
I thought you could only use a constant value/expression when declaring arrays...
[/quote]
Perhaps argc/argv are special? I have no idea why it works :)


Here's something else interesting that I noticed:
[code]int main()
{
main();
return 0;
}
[/code]
This will not compile on Linux. I get the error:
[code]iago@laptop:~/Projects/C$ gcc -Wall test2.cpp
/tmp/cc8BvbGZ.o(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
collect2: ld returned 1 exit status
iago@laptop:~/Projects/C$[/code]
[/quote]

gcc doesn't like *.cpp files. You need to use g++ or rename test2.cpp to test2.c.
April 27, 2004, 11:15 PM
Myndfyr
[quote author=Mephisto link=board=30;threadid=6491;start=15#msg57137 date=1083099734]
Arta, do you get that error when you try to declare an array with a non-constant value/expression?
[/quote]

I'm somewhat confused (perhaps due to my C newbletness), but I was under the impression that you *could* create variable-size arrays. Vis-a-vis:

[code]

int main()
{
cout << "Enter a value:" << endl;
int num = 0;
cin >> num;

int *array = malloc(num * sizeof(int));
if (array == NULL)
return 1;

//...
}
[/code]

and then you would effectively have an array with the size that you wanted. I can't remember if it can be cast or not... It seems like it should be able to, by setting an array pointer to the variable of the array itself.

Like I said though, I'm a C newblet, so I could be off.
April 27, 2004, 11:55 PM
K
C99 says you can do this:

[code]
int x = 10;

int Foo[x];
[/code]

you could do it like so:
[code]
int x = 10;
int *Foo = malloc(x * sizeof(int));
// ...
free(Foo);
[/code]

the difference is primarily that you have to free() the second, and where they are allocated.
April 28, 2004, 12:36 AM
iago
[quote author=K link=board=30;threadid=6491;start=15#msg57194 date=1083112568]
C99 says you can do this:

[code]
int x = 10;

int Foo[x];
[/code]

you could do it like so:
[code]
int x = 10;
int *Foo = malloc(x * sizeof(int));
// ...
free(Foo);
[/code]

the difference is primarily that you have to free() the second, and where they are allocated.
[/quote]

Also, you can return the second, it's on the heap, but you can't return the first one, it's on the stack and will get broken.
April 28, 2004, 1:02 AM
Arta
[quote author=Mephisto link=board=30;threadid=6491;start=15#msg57137 date=1083099734]
Arta, do you get that error when you try to declare an array with a non-constant value/expression?
[/quote]

Looks that way, yes. I get the same errors with:

[code]

int main(int argc, char **argv)
{
   int x = 10;

   int y[x];

   return 0;
}

[/code]

Perhaps there's a compiler option somewhere that controls this?

Edit: perhaps not - see ms-help://MS.VSCC/MS.MSDNVS/vccore/html/C2057.htm:

[quote]
expected constant expression

The context requires a constant expression. The following sample generates C2057:

// C2057.cpp
int i;
// use the line below to resolve the error
// const int i = 8;

int b[i]; // C2057

int main() {
}

[/quote]
April 28, 2004, 11:15 PM
Mephisto
That's what I thought. I could've sworn you could never use a non-constant value when declaring your array, though I don't see why you couldn't, it will always know how much memory to allocate. Perhaps some compilers now violate this? Or the standards have changed...?
April 28, 2004, 11:37 PM

Search