Reputation: 3747
As sizeof operator evaluates operand if it's a VLA so I tried to test it as :
#include<stdio.h>
int main(void)
{
int sz=20,i=0,j=0;
int arr[sz];
printf("%d\n",sizeof((++i,sz)));
printf("%d\n",sizeof((++j,arr)));
printf("%d\n%d\n",i,j);
}
I thought that i won't increment as sz is not VLA but j would increment as arr is VLA.
But in the output, none of the i and j incremented.
Upvotes: 2
Views: 536
Reputation: 134611
Not much of an explanation but I suspect it's some compiler optimization for the comma operator. The value of a comma operation is the value of the last expression. With the compiler knowing sizeof is a unary operator and presented with a comma operation, it doesn't bother to evaluate any but the last expression (regardless whether the last was a reference to a VLA or not).
I wrote some test programs (gcc 4.3.3 on Ubuntu 9.04):
$ cat test.c # with sizeof
#include <stdio.h>
int main(void)
{
int x = 0;
printf("%d\n",
sizeof( printf("%s%d\n", "comma!", ++x), x));
}
$ gcc -S test.c
$ cat test.s
.file "test.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $36, %esp
movl $0, -8(%ebp)
movl $4, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $36, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
Note the absences of the string literals and the second printf()
call.
$ cat test-alt.c # without sizeof
#include <stdio.h>
int main(void)
{
int x = 0;
printf("%d\n",
( printf("%s%d\n", "comma!", ++x), x));
}
$ gcc -S test-alt.c
$ cat test-alt.s
.file "test-alt.c"
.section .rodata
.LC0:
.string "comma!"
.LC1:
.string "%s%d\n"
.LC2:
.string "%d\n"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $36, %esp
movl $0, -8(%ebp)
addl $1, -8(%ebp)
movl -8(%ebp), %eax
movl %eax, 8(%esp)
movl $.LC0, 4(%esp)
movl $.LC1, (%esp)
call printf
movl -8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC2, (%esp)
call printf
addl $36, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
It may be documented somewhere but I wouldn't know where to look.
Upvotes: 2
Reputation: 96251
Quoting my answer to another question:
The "conversion" is due to the subtraction operator. You can see a similar, and perhaps more surprising, result with the comma operator:
printf("%zu\n", sizeof(1, a));
will also print
sizeof(int *)
, because of the comma operator resulting in a getting used in a value context.
Basically, due to the comma operator, the type of arr
is a pointer, and the size of the VLA doesn't come into the picture. See my linked answer for details.
Upvotes: 5
Reputation: 5715
sizeof evaluates at compile time. In C99 for variable length arrays it will wait until runtime. Check this answer to a similar question.
Upvotes: 1
Reputation: 43331
Compiler knows the array size: it is obviously 20. I don't think that sz is VLA. Try to use use array size as function parameter, for eaxmple:
void Function(int size) { int arr[size]; ... }
BTW, to understand what happens, it is recommended to read Assembly code produced by compiler. Check whether sizeof is replaced by a constant already at compile time.
Upvotes: 0