以下 C 代码的 RUST 等价物是什么?

one*_*ero 0 c stack-memory rust borrow-checker stack-pointer

我有一个小的 C 代码,它通过修改堆栈地址处的数据来演示运行时堆栈功能。

#include <stdio.h>

int * fun() {
    int a = 10;
    return &a;
}
int * fun2() {
    int b = 20;
    return &b;
}

int main () {
    int *a = fun();
    int *b = fun2();
    printf("a:%d b:%d\n", *a, *b);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

其输出为:a:20 b:20,显示“fun2”中的“b”使用与“fun”中的“a”相同的堆栈地址。

我也想在 Rust 中测试这个。做到这一点最简单的方法是什么?

我尝试借用,但编译器说“没有借用价值”。

Cha*_*man 7

如果你想拥有与 C 中相同的未定义行为,你可以这样做(幸运的是,这需要unsafe):

fn fun() -> *const i32 {
    let a = 10;
    &a
}

fn fun2() -> *const i32 {
    let b = 20;
    &b
}

fn main() {
    let a = fun();
    let b = fun2();
    // SAFETY: Don't do this. This is pure Undefined Behavior.
    unsafe {
        println!("a: {} b: {}", *a, *b);
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是 UB,与 C 版本完全相同。它在调试模式和发布模式下打印a: 21885 b: 21885在 Playground 上。a: -482758656 b: 32767你的会有所不同。

如果您还想要与 C 版本相同的结果,您可以使用printf(). 请小心您使用的代码,更改可能会导致它不再“工作”,因为它将使用不同的堆栈布局。当然,这是非常脆弱的:

use std::ffi::c_char;

fn fun() -> *const i32 {
    let a = 10;
    &a
}

fn fun2() -> *const i32 {
    let a = 20;
    &a
}

extern "C" {
    fn printf(format: *const c_char, ...);
}

fn main() {
    let a = fun();
    let b = fun2();
    unsafe {
        printf(b"a: %d b: %d\n\0" as *const u8 as *const c_char, *a, *b);
    }
}
Run Code Online (Sandbox Code Playgroud)

a: 20 b: 20在调试模式和a: 1 b: 1发布模式下打印(并且您的可能不同)。

  • 有道理。只是希望读者看到一个中的任何 UB 和另一个中的任何 UB 都可以归类为_相同_ - 两者都损坏了。 (4认同)
  • “具有与 C 中相同的未定义行为”可能比“具有与 C 中相同的未定义行为”更好。怀疑的人可以指定未定义的事物的相同性。 (3认同)