int main(){
int i = 0;
while(i < 2){
char str[10];
printf("%p\n", str); //outputs same address both the times
i++;
}
i = 0;
while(i<2){
char *str;
str = (char*)malloc(10*sizeof(char));
printf("%p\n", str); //outputs two different addresses
i++;
}
}
在上面的代码中,为什么在循环中声明相同的字符数组会给出相同的地址,尽管变量被声明两次不同的时间。所以根据我的理解,它应该为它分配新的内存。但它每次都返回相同的地址。
在动态分配内存的第二个中,它返回两个不同的地址,这是可以理解的,因为malloc每次都会为我找到新的连续内存块。
但是为什么它会在第一种情况下打印相同的地址?
答案 0 :(得分:7)
在您的第一个示例中,char str[10];
是仅在{
}
范围内有效的局部变量。范围结束后,变量被破坏并且内存被“释放”。下一个位置可以在同一个空间中,因为它是空的并且可用。
在第二个示例中,您使用malloc
...在您致电free
(或程序结束)之前,内存不会自动释放。
答案 1 :(得分:3)
在第一种情况下,char str[10]
在堆栈上分配一次,并且在程序停留在同一块{}
时保持指向它的指针。它没有被分配两次,即使你正在循环。并不是内存在神话}
的末尾变得“可用”,然后被“重新分配”,因为它再次可用。查看为第一部分生成的LLVM ir代码:
; 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
使用gcc -fdump-tree-all查看不同的解释阶段:
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>:
}
;; 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>:;
}