减少C中返回/传递的数据结构的大小


Reducing the size of returned/passed data structures in C

我正在麻省理工学院在线学习操作系统课程,我完成了第一个作业http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-828-operating-system-engineering-fall-2012/assignments/mit6 f12 ou assignment1.pdfb,但令我惊讶的是,他们如何返回数据结构,如何使用数据结构,并返回urn一个较小的数据结构,要使用它,只需将其重新转换。我看到它可以优化代码,但这是安全的吗?这是好的做法吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct small
{
    int  n ;
};

struct big
{
    int n ;
    char * string ;
};

struct small* f()
{
    struct big* x = malloc(sizeof(struct big));
    x->n = 'X';
    x->string = strdup("Nasty!");
    return (struct small*) x ;
}

int main(int argc, char *argv[])
{
    struct big *y = (struct big*)f();
    printf("%s
"
,y->string);
}

编辑1:这是麻省理工学院的链接,我只是用自己的代码复制了这个想法。http://ocw.mit.edu/courses/electrical engineering and computer science/6-828-operating-system-engineering-fall-2012/assignments/sh.c


  • 没有返回结构,只返回指向结构的指针。指针包含实际对象所在内存的地址。(在这种情况下,它是用malloc动态分配的,因此具有动态存储持续时间,并且将一直存在到pogram结束或指针上调用free)。

  • 该代码是合法的,并定义了语义。N1570草案的6.3.2.3/7表示


    A pointer to an object type may be converted to a pointer to a
    different object type. If the resulting pointer is not correctly
    aligned for the referenced type, the behavior is undefined. [does not apply here. -ps]
    Otherwise, when converted back again, the result shall compare equal
    to the original pointer.

  • 请注意,结构可能完全不相关(第一个数据元素不需要是相同的类型)。这种类型甚至可以是像int这样的内置类型。

    如果由于别名问题而通过错误类型(不是)的指针访问对象,则问题可能不同。


    要回答您的问题:

    Is it safe?

    显然不是。只需将指针的类型转换为其他类型,只有当您确信它是正确的类型时,才应该这样做。

    但是,如果你知道,一切都很好。

    Is it good practice?

    不,不是这个形状。

    有时用C语言以类似的方式进行面向对象编程(比较cpython的PyObject):使用一个"基"对象和一个"类型"结构,其结构如下:

    1
    2
    3
    4
    5
    6
    7
    8
    struct obj_type {
      const char* name;
      size_t length; // this is important so that you can copy the object later on without knowing its insides
    };

    struct obj_base {
      obj_type* type;
    };

    因为可以保证在C中,指向结构的指针指向其第一个元素的地址,所以可以使用在此基础上构建的其他对象:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    struct more_complex_object {
      obj_type* type;
      int value;
    };

    ...
    int main() {
      obj_type *more_complex_object_type = malloc(sizeof(obj_type));
      more_complex_object_type->name ="A more complex object type";
      more_complex_object_type->length = sizeof(more_complex_object);
      more_complex_object *obj = malloc(more_complex_object_type->length);
      obj->type = more_complex_object_type;
      obj->value = 10;
      ...
      //let's now use it as a simple instance of the"super" object
      obj_base* just_an_object = (obj_base*)more_complex_object;
      //when we copy things, we make sure to copy the full length:
      obj_base* target = malloc(sizeof(more_complex_object));
      memcpy(target, just_an_object, just_an_object->type->length);

      //now, when handling an object, we can check its type
      if(just_an_object->type == more_complex_object_type) {
        more_complex_object *my_obj = (more_complex_object)just_an_object;
        printf("value: %d
    "
    , my_obj->value);
      }
    }


    是的,它是安全的,只要您的编译器遵循C标准

    为什么GCC不优化结构?

    但不,我不认为这是一个好的做法。

    良好的实践是相对的,不应该作为一个规则来使用。如果要用C模拟OO继承行为,则需要使用此构造。