Pointers on C——8 Arrays.5

8.1.4 Pointer Efficiency

I stated earlier that pointers are sometimes more efficient than subscripts, assuming that they are used correctly. As they say on TV, your results may vary; it depends on your compiler and machine. However, the efficiency of your program depends primarily on the code you write, and it is just as easy to write bad code with pointers as it is with subscripts. In fact, it is probably easier.

前面我曾说过,指针有时比下标更有效率,前提是它们被正确地使用。就像电视上说的那样,你的结果可能不同,这取决于你的编译器和机器。然而,程序的效率主要取决于你所编写的代码。和使用下标一样,使用指针也很容易写出质量低劣的代码。事实上,这个可能性或许更大。


To illustrate some bad techniques as well as good ones, letʹs look at a simple function that copies the contents of one array into a second array using subscripts. We will analyze the assembly code produced for this function by one particular compiler for a computer using a processor from the Motorola M68000 family. We will then modify the function in various ways to use pointers and see what effect each modification has on the resulting object code.

为了说明一些拙劣的技巧和一些良好的技巧,让我们看一个简单的函数,它使用下标把一个数组的内容复制到另一个数组。我们将分析这个函数所产生的汇编代码,我们选择了一种特定的编译器,它在一台使用Motorola M68000 家族处理器的计算机上运行。我们接着将以不同的使用指针的方法修改这个函数,看看每次修改对结果目标代码有什么影响。


Before beginning the example, two cautions are in order. First, the way you write your program affects not only its runtime efficiency but also its readability. It is important not to sacrifice readability for negligible gains in efficiency. More will be said about this issue later.

在开始这个例子之前,要注意两件事情。首先,你编写程序的方法不仅影响程序的运行时效率,而且影响它的可读性。不要为了效率上的细微差别而牺牲可读性,这点非常重要。对于这个话题,我后面还要深入探讨。


Second, the assembly language shown is obviously specific to the 68000 family of processors. Other machines (and other compilers) may translate the programs differently. If you need the utmost efficiency for your environment, you can experiment as Iʹve done here to see how various source code idioms are implemented.

其次,这里所显示的汇编语言显然是68000 处理器家族特有的。其他机器(和其他编译器)可能会把程序翻译成其他样子。如果你需要在你的环境里取得最高效率,你可以在你的机器(和编译器)上试验我在这里所使用的各种方法,看看各种不同的源代码惯用法是如何实现的。


First, the following declarations apply to all versions of the function.

首先,下面的声明用于所有版本的函数。

#define SIZE 50

int x[SIZE];

int y[SIZE];

int I;

int *p1, *p2;

Here is the subscript version of the function.

void

try1()

{

for( i = 0; i < SIZE; i++ )

x[i] = y[i];

}

This version is pretty straightforward. The compiler produced the following assembly language code.


Letʹs walk through these instructions, one by one. First, the location containing the variable i is cleared, which implements the assignment to zero. Then execution jumps to the instruction labeled L20, which, with the following instruction, tests whether i is less than 50. If it is, execution jumps back up to the instruction labeled L20001.

让我们逐条分析这些指令。首先,包含变量i 的内存位置被清除,也就是实现赋值为零的操作。然后,执行流跳转到标签为L20 的指令,它和接下来的一条指令用于测试i 的值是否小于50 。如果是,执行流跳回到标签为L20001 的指令。


The instruction labeled L20001 begins the body of the loop. i is copied to register d0 where it is shifted left by two bits. The shift is used because it produces the same result as a multiplication by four but is faster. The address of the array y is then copied to address register a0.

标签为L20001 的指令开始了循环体。i 被复制到寄存器d0 ,然后左移2 位。之所以要使用移位操作,是因为它的结果和乘4 是一样的,但它的速度更快。接着,数组y 的地址被复制到地址寄存器a0 。


Now the same calculation that was previously performed on i is done again,but this time the result is put in register d1. Then the address of the array x is put into address register a1.

现在继续执行前面对i 的几个计算操作,但这次结果值置于寄存器d1然后数组x 的地址置于地址寄存器a1 。


The movl instruction with the complicated operands is what really does the work: the value that a0 + d0 points at is copied to the location that a1 + d1 points at.Then i is incremented, and compared to 50 to see if the loop should repeat.

带复杂操作数的movl 指令执行实际任务: a0+d0 所指向的值被复制到al+dl 所指向的内存位置。然后i 的值增加, 并与50 进行比较,看看是否应该继续循环。


Does it seem silly that the compiler evaluates the expression i * 4 twice, when i has not changed between the expressions? Well, this compiler is fairly old, and its optimizer isnʹt very smart. Modern compilers may do a better job, but maybe not. It is better to write good source code in the first place than to depend on the compiler to produce efficient object code from bad source code. Remember, though, that efficiency is not the only factor; usually the clarity of the code is more important.

编译器对表达式i*4进行了两次求值,你是不是觉得它有点笨?因为这两个表达式之间i 的值并没有发生改变。是的,这个编译器确实有点旧,它的优化器也不是很聪明。现代的编译器可能会表现得好一点,但也未必。和编写差劲的源代码,然后依赖编译器产生高效的目标代码相比,直接编写良好的源代码显然更好。但是,你必须记住,效率并不是唯一的因素,通常代码的简洁性更为重要。


上一章 Pointers on C——8 Arrays.4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值