如何在没有参考的情况下更改局部变量

use*_*114 -6 c

面试问题:不使用引用作为函数自变量或从函数返回值而更改局部变量值

void func()
{
  /*do some code to change the value of x*/
}
int main()
{
   int x = 100;
   printf("%d\n", x);  // it will print 100
   func(); // not return any value and reference of x also not sent
   printf("%d\n", x);  // it need to print 200
}
Run Code Online (Sandbox Code Playgroud)

x 价值需要改变

Kon*_*lph 8

答案是你做不到。

C编程语言无法做到这一点,并且尝试这样做总是会导致未定义的行为。这意味着不能保证结果会是什么。

现在,您可能很想利用未定义的行为来破坏C的运行时系统并更改值。但是,这是否以及如何工作完全取决于特定的执行环境。例如,当使用最新版本的GCC和clang编译代码并启用优化功能时,该变量将x不再存在于输出代码中:没有对应于其名称的存储位置,因此您甚至无法直接修改原始内存地址。

实际上,以上代码大致产生以下汇编输出:

main:
    subq    $8, %rsp
    movl    $100, %esi
    movl    $.LC0, %edi
    xorl    %eax, %eax
    call    printf
    xorl    %eax, %eax
    call    func
    movl    $100, %esi
    movl    $.LC0, %edi
    xorl    %eax, %eax
    call    printf
    xorl    %eax, %eax
    addq    $8, %rsp
    ret
Run Code Online (Sandbox Code Playgroud)

如您所见,该值100printf调用前直接存储在ESI寄存器中的文字。即使您func试图修改该寄存器,该修改也会被编译后的printf调用覆盖:

    …
    movl    $200, %esi /* This is the inlined `func` call! */
    movl    $100, %esi
    movl    $.LC0, %edi
    xorl    %eax, %eax
    call    printf
    …
Run Code Online (Sandbox Code Playgroud)

无论您将其切成小方块,答案是:x编译输出中没有变量,因此即使接受未定义的行为也无法修改它。您可以通过覆盖函数调用来修改输出printf,但这不是问题。


vir*_*ino 6

通过C语言的设计以及局部变量的定义,您不能在不以某种方式使它可用的情况下从外部访问它。

使局部变量可被外部访问的一些方法:

  • 发送它的副本(值);
  • 发送指向它的指针(不要保存和使用指针太长时间,因为该变量在其作用域结束时可能会被删除);
  • extern如果在文件级声明了变量,则将其导出(在所有函数之外)。


chu*_*ica 6

哈克:只需更改代码void func(),即可创建一个define
类似于@chqrlie

void func()
{
  /*do some code to change the value of x*/
  #define func() { x = 200; }
}

int main()
{
   int x = 100;
   printf("%d\n", x);  // it will print 100
   func(); // not return any value and reference of x also not sent
   printf("%d\n", x);  // it need to print 200
}
Run Code Online (Sandbox Code Playgroud)

输出量

100
200
Run Code Online (Sandbox Code Playgroud)