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

时间:2016-01-19 16:54:02

标签: c

我正在线上获取操作系统类,我完成了第一个分区http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-828-operating-system-engineering-fall-2012/assignments/MIT6_828F12_assignment1.pdf但是让我感到惊讶的是他们如何返回数据结构,他们使用数据结构并返回较小的数据结构,并使用它,他们只是将其转换回来。我看到它可以优化代码,但这样安全吗?这是好习惯吗?

#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\n",y->string);
}

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

3 个答案:

答案 0 :(得分:5)

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

  2. 代码合法且定义了语义。 n1570草案的6.3.2.3/7说

      

    指向对象类型的指针可以转换为指向a的指针   不同的对象类型。如果结果指针不正确   对于引用的类型,行为是未定义的。 [此处不适用。 -PS]   否则,当再次转换回来时,结果应该相等   到原始指针。

  3. 请注意,结构可能完全不相关(第一个数据元素不需要是同一类型)。演员阵容甚至可以是int等内置类型。

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

答案 1 :(得分:1)

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

,它就是安全的

Why doesn't GCC optimize structs?

但不,我认为这不是一个好习惯。

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

答案 2 :(得分:1)

回答你的问题:

  

安全吗?

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

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

  

这是好的做法吗?

不,不是这种形状。

您有时会以类似的方式在C中进行面向对象编程(比较CPython&#39; s 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; }; ):您使用一个&#34; base&#34;对象和一个&#34;类型&#34; struct具有如下结构:

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\n", my_obj->value);
  }
}

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

<LayoutTemplate>
    <table id="TimeSheet">
        <thead>
            <tr>
                <th id="thDelete" runat="server" Visible='<%# If( IsAdmin().tostring()="True", "true", "false") %>'>
                     Select
                </th>
            </tr>
        </thead>
        <tbody>
            <tr id="itemPlaceholder" runat="server" />
        </tbody>
    </table>
</LayoutTemplate>`