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:
#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;
}
*grin*
<edit> sample output:
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$
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...
Quote from: iago on April 26, 2004, 03:15 PM
#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;
}
*grin*
#include <stdio.h>
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.
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.
stdio? :p
Quote from: Mephisto on April 26, 2004, 05:54 PM
stdio? :p
bah, typo.. I deleted some global variables I stopped using and had to retype the include :P
Quote from: Adron on April 26, 2004, 04:16 PM
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.
It does when I compile it (under windows). I don't understand this either!
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. ;)
int main() {
int x = 5;
int array[x];
return 0;
}
Quote from: Mephisto on April 27, 2004, 09:13 AM
I thought you could only use a constant value/expression when declaring arrays...
Perhaps argc/argv are special? I have no idea why it works :)
Here's something else interesting that I noticed:
int main()
{
main();
return 0;
}
This will not compile on Linux. I get the error:
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$
Quote from: Mephisto on April 27, 2004, 09:13 AM
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. ;)
int main() {
int x = 5;
int array[x];
return 0;
}
Did you try running that with warnings?
I get this:
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$
it declares that variable "array" very weirdly :/
<edit>
I tried it on c, not c++, and it still works
iago@laptop:~/Projects/C$ gcc -Wall test.c
test.c: In function `main':
test.c:4: warning: unused variable `array'
iago@laptop:~/Projects/C$
Ouch, my brain :(
In case somebody's curious, this program:
#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;
}
compiles fine, on Linux, and produces the main function:
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
I don't have time right now to figure out how this is working, but feel free :)
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 from: iago on April 27, 2004, 09:28 AM
subl %eax, %esp
Quote from: Yoni on April 27, 2004, 10:10 AM
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 from: iago on April 27, 2004, 09:28 AM
subl %eax, %esp
Wow,that's smart, it subtracts the variable from esp :) *impressed*
iago@laptop:~/Projects/C$ gcc -ansi -fno-nonansi-builtins -Wall test2.cpp
iago@laptop:~/Projects/C$
works fine :)
<edit> I think -ansi means standard C89.
I had no idea this was allowed. hmm.
Well, I copied your code straight over:
error C2466: cannot allocate an array of constant size 0
error C2057: expected constant expression
error C2133: 'buffer' : unknown size
Although I think I see how it works now.. Kind've intentionally overflowing the stack - clever :)
Quote from: Arta[vL] on April 27, 2004, 02:21 PM
Well, I copied your code straight over:
error C2466: cannot allocate an array of constant size 0
error C2057: expected constant expression
error C2133: 'buffer' : unknown size
Although I think I see how it works now.. Kind've intentionally overflowing the stack - clever :)
Try making my array a constant size of "1"
Arta, do you get that error when you try to declare an array with a non-constant value/expression?
Quote from: iago on April 27, 2004, 09:18 AM
Quote from: Mephisto on April 27, 2004, 09:13 AM
I thought you could only use a constant value/expression when declaring arrays...
Perhaps argc/argv are special? I have no idea why it works :)
Here's something else interesting that I noticed:
int main()
{
main();
return 0;
}
This will not compile on Linux. I get the error:
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$
gcc doesn't like *.cpp files. You need to use g++ or rename test2.cpp to test2.c.
Quote from: Mephisto on April 27, 2004, 04:02 PM
Arta, do you get that error when you try to declare an array with a non-constant value/expression?
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:
int main()
{
cout << "Enter a value:" << endl;
int num = 0;
cin >> num;
int *array = malloc(num * sizeof(int));
if (array == NULL)
return 1;
//...
}
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.
C99 says you can do this:
int x = 10;
int Foo[x];
you could do it like so:
int x = 10;
int *Foo = malloc(x * sizeof(int));
// ...
free(Foo);
the difference is primarily that you have to free() the second, and where they are allocated.
Quote from: K on April 27, 2004, 07:36 PM
C99 says you can do this:
int x = 10;
int Foo[x];
you could do it like so:
int x = 10;
int *Foo = malloc(x * sizeof(int));
// ...
free(Foo);
the difference is primarily that you have to free() the second, and where they are allocated.
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.
Quote from: Mephisto on April 27, 2004, 04:02 PM
Arta, do you get that error when you try to declare an array with a non-constant value/expression?
Looks that way, yes. I get the same errors with:
int main(int argc, char **argv)
{
int x = 10;
int y[x];
return 0;
}
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; // C2057
int main() {
}
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...?