我最近遇到了一个由this question解释的C结构初始化的示例。
我不明白的是递归定义。这是从MicroPython/objtype.c
typedef struct _mp_obj_type_t mp_obj_type_t;
const mp_obj_type_t mp_type_type = { // <-- SAME SYMBOL DEFINED HERE . . .
{ &mp_type_type }, // <-- IS USED HERE
.name = MP_QSTR_type,
.print = type_print,
.make_new = type_make_new,
.call = type_call,
.unary_op = mp_generic_unary_op,
.attr = type_attr,
};
我了解
.<some_field>
指定的字段(请参见第一句中的链接)。但是关于“递归”初始化呢?
MicroPython code中还有其他使用以下语法的实例:
const mp_obj_type_t pyb_led_type = {
{ &mp_type_type }, <-- SAME SYMBOL AS ABOVE
.name = MP_QSTR_LED,
.print = led_obj_print,
.make_new = led_obj_make_new,
.locals_dict = (mp_obj_t)&led_locals_dict,
};
这更有意义:struct
pyb_led_type
使用在struct mp_type_type
中设置的默认值初始化,并且某些字段从默认值更改。但是
const mp_obj_type_t mp_type_type
呢?结构
mp_type_type
默认为的值。 。 。结构mp_type_type
。 。 。 ???预处理后的输出与
.c
相同。这里发生了什么?
这是该结构的一些字段
struct _mp_obj_type_t {
// A type is an object so must start with this entry, which points to mp_type_type.
mp_obj_base_t base;
// The name of this type.
qstr name;
// Corresponds to __repr__ and __str__ special methods.
mp_print_fun_t print;
...
};
struct _mp_obj_base_t {
const mp_obj_type_t *type MICROPY_OBJ_BASE_ALIGNMENT;
};
typedef struct _mp_obj_base_t mp_obj_base_t;
最佳答案
C语言中的自引用结构
您引用的MicroPython代码只是创建一个自引用的struct实例,这在C语言中是完美的。考虑一下这个示例,您几乎从示例中去除了一些不必要的部分:
#include "stdio.h"
// const base
struct A {
const struct A* base;
};
// non-const base
struct B {
const struct B* base;
};
const struct A a = { &a };
const struct B b = { &b };
int main() {
printf("%p %p\n", (void*) &a, (void*)a.base);
printf("%p %p\n", (void*) &b, (void*)b.base);
return 0;
}
在MicroPython代码中实例化
mp_obj_type_t
结构的特定用途MicroPython项目使用
base
指针在Python中实现(多个)继承。 base
引用是指向另一个类型的指针,该类型是基本类型(在类型层次结构中为“父”),请查看definition of this struct:struct _mp_obj_type_t {
// A type is an object so must start with this entry, which points to mp_type_type.
mp_obj_base_t base;
// .. many more fields
}
您提到的情况是
mp_type_type
const变量似乎是所有类型的基本类型,因此是自引用,但是当您查看从mp_type_type
“继承”的类型(例如pyb_led_type
)时,它就更有意义了:const mp_obj_type_t pyb_led_type = {
{ &mp_type_type },
.name = MP_QSTR_LED,
.print = led_obj_print,
.make_new = led_obj_make_new,
.locals_dict = (mp_obj_t)&led_locals_dict, };