Rust存储所有这些字节在哪里?

tsh*_*ang 7 rust

在尝试理解堆栈内存的工作原理时,我编写了以下代码来显示数据存储位置的地址:

fn main() {
    let a = "0123456789abcdef0";
    let b = "123456789abcdef01";
    let c = "23456789abcdef012";

    println!("{:p} {}", &a, a.len());
    println!("{:p} {}", &b, b.len());
    println!("{:p} {}", &c, c.len());
}
Run Code Online (Sandbox Code Playgroud)

输出是:

0x7fff288a5448 17
0x7fff288a5438 17
0x7fff288a5428 17
Run Code Online (Sandbox Code Playgroud)

这意味着所有17个字节都存储在16个字节的空间中,这可能不对.我的一个猜测是,有一些优化正在发生,但即使我构建时也得到相同的结果--opt-level 0.

等效的C似乎做对了:

#include <stdio.h>
#include <string.h>

int main() {
    char a[] = "0123456789abcdef";
    char b[] = "123456789abcdef0";
    char c[] = "23456789abcdef01";

    printf("%p %zu\n", &a, strlen(a) + 1);
    printf("%p %zu\n", &b, strlen(b) + 1);
    printf("%p %zu\n", &c, strlen(c) + 1);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0x7fff5837b440 17
0x7fff5837b420 17
0x7fff5837b400 17
Run Code Online (Sandbox Code Playgroud)

huo*_*uon 7

字符串字面"..."存储在静态存储器和变量a,b,c只是(脂肪)指向他们.它们有类型&str,具有以下布局:

struct StrSlice {
    data: *const u8,
    length: uint
}
Run Code Online (Sandbox Code Playgroud)

其中data场点,形成文本的字节序列,并length现场说多少字节有.

在64位平台上,这是16字节(在32位平台上,8字节).C中的实际等价物(忽略空终止与存储长度)将存储为a const char*而不是a char[],将C更改为此打印:

0x7fff21254508 17
0x7fff21254500 17
0x7fff212544f8 17
Run Code Online (Sandbox Code Playgroud)

即指针间隔8个字节.

您可以使用--emit=asm或查看这些低级别详细信息--emit=llvm-ir,或单击该游戏围栏上的相应按钮(也可能会调整优化级别).例如

fn main() {
    let a = "0123456789abcdef0";
}
Run Code Online (Sandbox Code Playgroud)

编译时--emit=llvm-ir没有优化(使用我的修剪和注释):

%str_slice = type { i8*, i64 }

;; global constant with the string's text
@str1042 = internal constant [17 x i8] c"0123456789abcdef0"

; Function Attrs: uwtable
define internal void @_ZN4main20h55efe3c71b4bb8f4eaaE() unnamed_addr #0 {
entry-block:
  ;; create stack space for the `a` variable
  %a = alloca %str_slice

  ;; get a pointer to the first element of the `a` struct (`data`)...
  %0 = getelementptr inbounds %str_slice* %a, i32 0, i32 0
  ;; ... and store the pointer to the string data in it
  store i8* getelementptr inbounds ([17 x i8]* @str1042, i32 0, i32 0), i8** %0

  ;; get a pointer to the second element of the `a` struct (`length`)...
  %1 = getelementptr inbounds %str_slice* %a, i32 0, i32 1
  ;; ... and store the length of the string (17) in it.
  store i64 17, i64* %1
  ret void
}
Run Code Online (Sandbox Code Playgroud)