编译器比你聪明


#22

其实C也不用到处void*的,现在C都能const了。

p.s. 54我手滑……我以为“存档”是“保存到本地”呢


#23

用宏还是用内联函数?

有的人喜欢把会被非常频繁调用的函数改用 实现. 因为他们说, 这样会避免掉函数调用, 提升效率.

但是宏的坑也很明显, 太多了, 你永远写不出一个正确的获取最大值和最小值的 MAX MIN 宏.

那么, 为什么不使用内联函数呢?


inline int max(int a , int b ){
  return   a>b ? a: b;
}

像这样一个内联函数, 非常的简单, 谁都能第一次就写正确, 可是如果是宏, 你能保证你写的正确么?

那么, 编译器对于这样的代码到底会不会优化呢?

我们写一个测试函数


#define MAX(a,b)   ( (a) > (b) ? (a) : (b)  )
inline int  max(int a , int b )
{
        return a > b ? a : b;
}


int foo()
{
        return  max(2,4);
}

int foo2()
{
        return MAX(2,4);
}

对于这样的代码, 不论是 foo 还是 foo2, 编译器都只生成了 2条指令

movl 4, %eax
ret

#24

使用inline,前提是需要保证层次有限,是这样吧?


#25

内联总结

编译器总是能为内联的函数生成和宏定义一样高效的代码. 但是使用内联函数能获得额外的好处, 比如类型检查. 相比宏定义更好的可读性, 更容易调试.


结论是不要为了所谓的效率去编写晦涩难懂的宏


#26
#define MAX(a,b)  ((a)>(b)?(a):(b))

int i = 3;
int a = MAX(i++, 2)
cout << "Now i is " << i << endl;

好像这样就错了!


#27

对啊, 要想写出正确的宏非常难


#28

C几乎是没办法的事,是离不开void的,很多情况下,你必须要用void来实现多态,上下文指针等等。


#29

如果是一个inline函数调用另外一个inline呢,这样的层次多了,编译器还能优化么


#30

宏如果嵌套太多, 你还能看的懂么? 根本就写不出来了吧.

如果真的要编译器强制嵌套太多的内联不要放弃内联, 可以使用编译器参数, 但是强烈不建议这么做. 编译器取消内联是因为编译器发现不内联更好. 你要相信编译器比你更懂CPU


#31

inline 只适用于小函数 编译器有许多优化策略


#32

inline会展开的,如果在死循环里用,那就死翘翘了。


#33

我写C一般绕开这些高级东西……因为我看着void*就难受


#34

对于一些小函数, 甚至你不需要写上 inline, 编译器就能自动的优化.


#35

下面要说的一个优化会让很多人大跌眼镜

编译器能消除很多冗余的检查代码!

static char array[100000];
static int write_to(int ofs,char val) {
    if (ofs>=0 && ofs<100000)
          array[ofs]=val;
}
int main() {
   int i;
   for (i=0; i<100000; ++i) array[i]=0;
   for (i=0; i<100000; ++i) write_to(i,-1);
}

上面这段代码, write_to 和 直接的数组访问, 生成的是一模一样的代码! 这还不包括 write_to 是个函数调用, 同时内部包含了边界检查!!!


#36

写C,我有时候就用用,jack提到的联合和结构,两种形式。


#37

然后顶回来……就看的到了哈哈哈哈


#38

在上面这段循环代码里, 编译器不仅仅消除了 write_to 调用, 同时消除了边界检查, 同时 编译器还自动的使用了 SSE 进行了优化.


#39

编译器是怎样做到这种优化的呢?>


#40

对于适量化, 就是编译器将循环使用 SIMD 指令优化, 如如下的一段代码

int zero(char* array) {
    unsigned long i;
    for (i=0; i<1024; ++i)
        array[i]=23;
}

编译器将对 array 数组的操作使用 每次写入 128位的 SSE 指令, 只需 循环 64次即可完成数组赋值操作 !!!

所以, 无论如何, 对于支持 SSE 的CPU请一定告诉编译器, 好让编译器进行 SIMD 优化!


#41

PS MSVC 编译器对上面的代码的优化就是替换成了一个 memset 调用.