过度的开发技巧

在 quake3 和 halflife2 的代码中发现如下代码:
 
 bspbrush_t *bb;
 int   c;
 c = (int)&(((bspbrush_t *)0)->sides[numsides]);
 bb = (bspbrush_t*)malloc(c);
 
这段代码的作用是分配内存,刚开始我看不出这样做有什么好处,后来仔细看了一下函数声明:
 
bspbrush_t *AllocBrush (int numsides)
 
使用这种方式就可以分配可变大小 bspbrush_t 的内存,sides 成员是另外一个结构体的数组,这样可以不用分配无用的内存,按需分配内存,这种分配内存方式还是头一次遇见。
Advertisements
此条目发表在3D图形分类目录。将固定链接加入收藏夹。

5 Responses to 过度的开发技巧

  1. 说道:

    这种方式我在其他地方也见到过。就象一个运行时的 sizeof。
    做到不分配无用内存很容易,这种计算方式可能比较节省指令。

  2. 说道:

    它应该是利用了编译器对特定情况的处理机制。这种表达式:
    &(((bspbrush_t *)0)->sides[numsides]);
    编译器很容易的就能生成最简单的指令。可能和手写汇编差不多。如果自己计算内存大小应该这么写:
    sizeof( sides) * numsides
    编译器生成的指令要 mov 来 mov 去的。有冗余。

  3. 说道:

    前面有个地方说错了,应该是 sizeof( sides中成员的类型)*numsides

  4. 说道:

    既然sizeof是编译时决定,就不可能生成汇编指令,这种方法反而还要多用一些指令。
    不过倒是可以使用这种方法来实现自己的sizeof函数,比如:
    struct s{ int a, b, c }
    len=(int)&(((char*)&(((aaa*)0)->c))[4]);
    虽然不是编译时的。

  5. 说道:

    sizeof 是不生成指令的,但是 sizeof 和 numsides 相乘需要好几条指令。
    编译器发现代码里引用处理数组中的单元时,背地里偷偷的也做了同样的操作,以取得该单元合适的内存地址,但此时生成的指令是编译器能做到的最简化版本。

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  更改 )

Google+ photo

You are commenting using your Google+ account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

w

Connecting to %s