In the first case the char str[10] is allocated on the stack once, and the pointer to it is maintained while the program stays in the same block {}. It's not allocated twice, even though you're looping. It is NOT that the memory becomes "available" at the end of the mythical } and then gets "reassigned" because it was available again. Look at LLVM ir code that's generated for the first part:
; Function Attrs: nounwind uwtable
define i32 @main() #0 {
%1 = alloca i32, align 4
%i = alloca i32, align 4
; actuall allocation of str as a 10 byte value
; occurs OUTSIDE the looping labels
; and deallocation also occurs outside the looping
; label (see label 10)
%str = alloca [10 x i8], align 1
%str1 = alloca i8*, align 8
store i32 0, i32* %1
store i32 0, i32* %i, align 4
br label %2
; this is the opening {
; <label>:2 ; preds = %5, %0
%3 = load i32* %i, align 4
%4 = icmp slt i32 %3, 2
; LOOP breaks out on the condition matching i>2
br i1 %4, label %5, label %10
; <label>:5 ; preds = %2
%6 = getelementptr inbounds [10 x i8]* %str, i32 0, i32 0
%7 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %6)
%8 = load i32* %i, align 4
%9 = add nsw i32 %8, 1
store i32 %9, i32* %i, align 4
; LOOP back to label %2 which does NOT include the
; original allocation logic between here and there logic
; this is the closing }
br label %2
; DEALLOCATION occurs here
; <label>:10 ; preds = %2
store i32 0, i32* %i, align 4
br label %11
here is the same code using gcc
use gcc -fdump-tree-all to see different stages of interpretation:
gimple
main ()
{
int i;
i = 0;
goto <D.2181>;
<D.2180>:
{
char str[10];
try
{
printf ("%p\n", &str);
i = i + 1;
}
finally
{
str = {CLOBBER};
}
}
<D.2181>:
if (i <= 1) goto <D.2180>; else goto <D.2182>;
<D.2182>:
i = 0;
goto <D.2186>;
<D.2185>:
{
char * str;
extern void * malloc (long unsigned int);
str = malloc (10);
printf ("%p\n", str);
i = i + 1;
}
<D.2186>:
if (i <= 1) goto <D.2185>; else goto <D.2187>;
<D.2187>:
}
original
;; Function main (null)
;; enabled by -tree-original
{
int i = 0;
int i = 0;
goto <D.2181>;
<D.2180>:;
{
char str[10];
char str[10];
printf ((const char * restrict) "%p\n", (char *) &str);
i++ ;
}
<D.2181>:;
if (i <= 1) goto <D.2180>; else goto <D.2182>;
<D.2182>:;
i = 0;
goto <D.2186>;
<D.2185>:;
{
char * str;
extern void * malloc (long unsigned int);
char * str;
str = (char *) malloc (10);
printf ((const char * restrict) "%p\n", str);
i++ ;
}
<D.2186>:;
if (i <= 1) goto <D.2185>; else goto <D.2187>;
<D.2187>:;
}