简体   繁体   English

Rust - repr(C) 是预处理器指令吗?

[英]Rust - Is repr(C) a preprocessor directive?

I've seen some Rust codebases use #[repr(C)] macro (is that what it's called?) , however, I couldn't find much information but that it sets the type layout in memory to the same layout as 'C's.我已经看到一些 Rust 代码库使用#[repr(C)](这就是所谓的吗?) ,但是,我找不到太多信息,但它将 memory 中的类型布局设置为与“C”相同的布局.

Here's what I would like to know: is this a preprocessor directive restricted to the compiler and not the language itself (even though there aren't any other compiler front-ends for Rust), and why does Rust even have a memory layout different than that of Cs?这是我想知道的:这是一个仅限于编译器而不是语言本身的预处理器指令(即使没有任何其他用于 Rust 的编译器前端),为什么 Rust 甚至有一个 memory 布局不同于Cs的那个? (it's just that I've never had to do this in another language). (只是我从来不需要用另一种语言来做这件事)。 Thanks.谢谢。

Edit: Here's a nice situation to demonstrate what I meant;编辑:这是一个很好的情况来证明我的意思; if someone creates another compiler for Rust, are they required to implement this macro, or is it a compiler specific thing?如果有人为 Rust 创建另一个编译器,他们是否需要实现这个宏,或者它是编译器特定的东西?

#[repr(C)] is not a preprocessor directive, since Rust doesn't use a preprocessor 1 . #[repr(C)]不是预处理器指令,因为 Rust 不使用预处理器1 It is an attribute .它是一个属性 Rust doesn't have a complete specification, but the repr attribute is mentioned in the Rust reference , so it is absolutely a part of the language. Rust 没有完整的规范,但是在 Rust 参考文献中提到repr属性,所以它绝对是语言的一部分。 Implementation-wise, attributes are parsed the same way all other Rust code is, and are stored in the same AST.在实现方面,属性的解析方式与所有其他 Rust 代码相同,并且存储在相同的 AST 中。 Rust has no "attribute pass": attributes are an actual part of the language. Rust 没有“属性传递”:属性是语言的实际部分。 If someone else were to implement a Rust compiler, they would need to implement #[repr(C)] .如果其他人要实现 Rust 编译器,他们将需要实现#[repr(C)]

Furthermore, #[repr(C)] can't be implemented without some compiler magic.此外,如果没有一些编译器魔法, #[repr(C)]就无法实现。 In the absence of a #[repr(...)] , Rust compilers are free to arrange the fields of a struct / enum however they want to (and they do take advantage of this for optimization purposes.).在没有#[repr(...)]的情况下,Rust 编译器可以随意排列struct / enum的字段(并且他们确实利用这一点进行优化。)。

Rust does have a good reason for using it's own memory layout. Rust 确实有充分的理由使用它自己的 memory 布局。 If compilers aren't tied to how a struct is written in the source code, they can do optimisations like not storing struct fields that are never read from, reordering fields for better performance, enum tag pooling 2 , and using spare bits throughout NonZero* s in the struct to store data (the last one isn't happening yet, but might in the future).如果编译器不依赖于源代码中struct的编写方式,他们可以进行优化,例如不存储永远不会读取的struct字段、重新排序字段以获得更好的性能、 enum标记池2以及在整个NonZero*中使用备用位s 在结构中存储数据(最后一个还没有发生,但将来可能会发生)。 But the main reason is that Rust has things that just don't make sense in C.但主要原因是 Rust 有一些在 C 中没有意义的东西。 For instance, Rust has zero-sized types (like () and [i8; 0] ) which can't exist in C , trait vtables, enum s with fields, generic types, all of which cause problems when trying to translate them to C.例如, Rust 具有零大小的类型(如()[i8; 0],这些类型在 C 中不存在trait vtables,带有字段的enum ,泛型类型,所有这些都会在尝试将它们转换为C。


1 Okay, you could use the C preprocessor with Rust if you really wanted to. 1好的,如果你真的想的话,你可以使用 C 预处理器和 Rust。 Please don't.请不要。

2 For example, enum Food { Apple, Pizza(Topping) } enum Topping { Pineapple, Mushroom, Garlic } can be stored in just 1 byte since there are only 4 possible Food values that can be created. 2例如, enum Food { Apple, Pizza(Topping) } enum Topping { Pineapple, Mushroom, Garlic }只能存储在 1 个字节中,因为只能创建 4 个可能的Food值。

What is this?这是什么?

It is not a macro it is an attribute.它不是一个宏,它是一个属性。

The book has a good chapter on what macros are and it mentions that there are "Attribute-like macros":这本书有一个关于宏是什么的好章节,它提到有“类似属性的宏”:

The term macro refers to a family of features in Rust: declarative macros with macro_rules: and three kinds of procedural macros:宏一词是指 Rust 中的一系列功能:具有宏规则的声明性宏:和三种过程宏:

  • Custom #[derive] macros that specify code added with the derive attribute used on structs and enums自定义 #[derive] 宏,指定使用结构和枚举使用的派生属性添加的代码
  • Attribute-like macros that define custom attributes usable on any item定义可用于任何项目的自定义属性的类属性宏
  • Function-like macros that look like function calls but operate on the tokens specified as their argument类似函数的宏,看起来像 function 调用,但对指定为其参数的标记进行操作

Attribute-like macros are what you could use like attributes.类似属性的宏是您可以使用的类似属性的宏。 For example:例如:

#[route(GET, "/")]
fn index() {}

It does look like the repr attribute doesn't it它看起来像repr属性不是吗

So what is an attribute then?那么什么是属性呢?

Luckily Rust has great resources like rust-by-example which includes :幸运的是,Rust 拥有丰富的资源,例如 rust-by-example ,其中包括

An attribute is metadata applied to some module, crate or item.属性是应用于某些模块、板条箱或项目的元数据。 This metadata can be used to/for:此元数据可用于/用于:

  • conditional compilation of code代码的条件编译
  • set crate name, version and type (binary or library)设置 crate 名称、版本和类型(二进制或库)
  • disable lints (warnings)禁用 lints(警告)
  • enable compiler features (macros, glob imports, etc.)启用编译器功能(宏、全局导入等)
  • link to a foreign library链接到外国图书馆
  • mark functions as unit tests将函数标记为单元测试
  • mark functions that will be part of a benchmark标记将成为基准的函数

The rust reference is also something you usually look at when you need to know something more in depth. rust 参考资料也是您在需要更深入了解时通常会查看的内容。 ( chapter for attributes ) 属性章节

To the compiler authors out there:对于那里的编译器作者:

If you were to write a rust compiler, and wanted to support things like the standard library or other crates then you would 100% need to implement these.如果您要编写 rust 编译器,并且想要支持标准库或其他 crate 之类的东西,那么您将 100% 需要实现这些。 Because the libraries use these and need them.因为图书馆使用这些并且需要它们。

Otherwise I guess you could come up with a subset of rust that your compiler supports.否则我猜你可能会想出你的编译器支持的 rust 的一个子集。 But then most people wouldn't use it..但是大多数人不会使用它..

Why does rust not just use the C layout?为什么 rust 不只是使用 C 布局?

The nomicon explains why rust needs to be able to reorder fields of structs for example.例如,该书解释了为什么 rust 需要能够重新排序结构的字段。 For reasons of saving space and being more efficient.出于节省空间和提高效率的原因。 It is related to, among other things, generics and monomorphization.它与 generics 和单态化等有关。 In repr(C) fields of structs must be in the same order as the definition.repr(C)中,结构的字段必须与定义的顺序相同。

The C representation is designed for dual purposes. C 表示是为双重目的而设计的。 One purpose is for creating types that are interoperable with the C Language.一个目的是创建可与 C 语言互操作的类型。 The second purpose is to create types that you can soundly perform operations on that rely on data layout such as reinterpreting values as a different type.第二个目的是创建可以可靠地执行依赖于数据布局的操作的类型,例如将值重新解释为不同的类型。

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

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