编译器是否足够智能来优化它?

时间:2015-11-27 19:22:57

标签: c

以下几行:

typedef struct foo {.....} foo_t;
foo_t array[1000];
foo_t* ptr = &array[50];

最后一行是否等同于

 foo_t* ptr = array + 50

因为假设foo_t很大,将array[50]转换为foo_t的实例,然后获取地址会很昂贵。

1 个答案:

答案 0 :(得分:0)

假设编译器合理,编译器应生成等效的:

ptr = (char*)array + 50 * sizeof(foo_t); 

对于这两种情况,是的。 (转化为char*只是为了表示需要将sizeof(foo_t)乘以声明。

无论如何,实际上没有其他方法可以找到&array[50]的值。

请注意50 * sizeof(foo_t)的关键点是,在添加到array的基址之前,我们需要MULTIPLY索引来生成字节地址值。对于典型情况,array的地址是常量且偏移量是常数[sizeof(foo_t)本质上是常量,或者你不能声明变量的数组],编译器的意思是当然,优化整个array + 50 * sizeof(foo_t)使得它只是代码中的常量(一旦它被链接并重新定位到数据地址)。

如果50x替换,这是一个仅在运行时知道的值,那么在add之前会有一个乘法[如果被乘数足够简单,则可以将乘法优化为更快的操作,例如x * 9 = x * 8 + x作为一条指令,因为有支持乘以1,2,4,8和16 - 至少在某些处理器,甚至是RISC处理器中,乘法通常比a很少添加和移位操作 - 小数字通常很容易处理这种方式,但575或13412可能不那么容易转换为少量的简单操作,因此需要适当的乘法。

但不管怎样,&array[50]array + 50的地址计算都是相同的 - 99%肯定会在编译时计算出来。如果在编译时未知,则对array + xx + array&array[x]&x[array]执行相同的计算 - 因为array[x]*(array + x) (并且使用地址运算符将只删除对元素1的实际访问权限)与语言定义相同,并且这种转换很早就在编译阶段发生,因此它们在后面变得无法区分 - 实际执行代码生成的结束。

1在我的Pascal编译器中,我有一个函数用于执行Address的抽象语法树类,并且对变量值的访问是value = Load(AST.Address())Store(value, AST.Address())作为通用解决方案。参见:

General "Load value".

Calculate address of [multidimensional] array