简体   繁体   English

if块中返回一个自动值?

[英]return a auto value in if block?

#include <stdio.h>

static int test(int val)
{
    int *ptr;

    if(val == 0)
    {
        int val = 4;
        ptr = &val;
    }

    return (*ptr + 1);
}

int main(void)
{
    int i = test(0);
    printf("%d\n", i);
    return 0;
}

In the above code, the variable val in if block is destroyed, so in return (*ptr + 1) , the value *ptr should be undefined, but result of this program is 5 . 在上面的代码中,if块中的变量val被销毁,因此在return (*ptr + 1) ,值*ptr应该是未定义的,但是该程序的结果是5

I know this is a undefined program, but it seems that it produces a expected value, why? 我知道这是一个未定义的程序,但它似乎产生了预期的价值,为什么?

As already stated in the comments, it is undefined behaviour - so anything can happen. 正如评论中已经说明的那样,它是未定义的行为 - 因此任何事情都可能发生。

However, technically , the reason is that the stack frame is not changed after leaving the if block, and that the compiler allocates all required local variables for the whole function at the beginning of the function, instead of creating a new stack frame for each scope. 但是,从技术上讲 ,原因是在离开if块后堆栈帧没有改变,并且编译器在函数开头为整个函数分配所有必需的局部变量,而不是为每个作用域创建一个新的堆栈帧。 You can see this in the assembly code which is produced by your function: 您可以在函数生成的汇编代码中看到:

ZL4testi:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp          ; set up base pointer for stack frame
                                    ; NOTE: The stack pointer is not modified here
                                    ; since you are not calling any other function
                                    ; from within `test`
        .cfi_def_cfa_register 6
        movl    %edi, -20(%rbp)     ; parameter was passed in %edi, store it in the frame

; if (parameter val == 0)
        cmpl    $0, -20(%rbp)       
        jne     .L2

; Here the scope of the `if` block starts - no changes to the stack frame setup!
; {
;    int val = 4
        movl    $4, -4(%rbp)        ; val is at -4(%rbp)

;    ptr = &val;
        leaq    -4(%rbp), %rax      ; get address of val into %eax
        movq    %rax, -16(%rbp)     ; store address of val into ptr
; }
.L2:
        movq    -16(%rbp), %rax     ; Here, ptr is still containing the address 
                                    ; of val within the stack frame
        movl    (%rax), %eax        ; load `val` from the stack even though it is out of scope
        addl    $1, %eax

        popq    %rbp
        .cfi_def_cfa 7, 8
        ret

Throughout the whole function, the stack frame layout is 在整个功能中,堆栈框架布局是

-20(%rbp)  => parameter val
-16(%rbp)  => ptr
 -4(%rbp)  => variable val inside the `if` block

Note that nothing prevents the compiler from reusing -4(%rbp) if you declare a new variable inside another scope at a later point inside your function: 请注意,如果您在函数内部稍后的位置声明另一个范围内的新变量,则不会阻止编译器重用 -4(%rbp)

static int test(int val) {
    int *ptr;

    if(val == 0) {
        int val = 4;
        ptr = &val;
    }
    if(val == 0) {
        int otherval = 6;
        ptr = &otherval;
    }
    return (*ptr + 1);
}

If you compare the previous assembly output with the one which is generated with the additional block in place, the only difference are these additional lines: 如果将先前的装配输出与使用附加块生成的装配输出进行比较,则唯一的区别是这些附加线:

    cmpl    $0, -20(%rbp)
    jne .L3

    movl    $6, -4(%rbp)      ; here, -4(%rbp) is reused for otherval
    leaq    -4(%rbp), %rax
    movq    %rax, -16(%rbp)
.L3:

I don't see val being destroyed, simply changed to 4. 我没有看到val被破坏,只是改为4。

ptr is then given the value of 4 然后ptr的值为4

So 4+1 = 5 所以4 + 1 = 5

Maybe I'm missing something completely. 也许我完全错过了一些东西。

The function evaluates (*ptr + 1) to 5, and returns the 5. Nothing undefined here. 函数将(* ptr + 1)计算为5,并返回5.此处未定义任何内容。 If you want undefined behaviour, return the pointer, and access the memory through the pointer in main . 如果您想要未定义的行为,请返回指针,并通过main的指针访问内存。

if you check the address of each pointer you can remark that is not the same address pointer: 如果你检查每个指针的地址,你可以注释不是相同的地址指针:

    #include <stdio.h>

    static int test(int val)
    {
        int *ptr;

        if(val == 0)
        {
            int val = 4;
            ptr = &val;
        }
        printf("ptr @ = %p \n",ptr);
        printf("val @ = %p \n",&val);
        return (*ptr + 1);
    }

int main(void)
{
    int i = test(0);
    printf("%d \n", i);
    return 0;
}  

==> 
    result :
    ptr @ = 0x7fff8b480874 
    val @ = 0x7fff8b48086c 
    5  

==> is undefined behaviour but the difference between address of pointer can explain why the variable "i" have the good value ==>是未定义的行为,但指针地址之间的差异可以解释为什么变量“i”具有良好的值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM