Pointers on C——8 Arrays.6

Switching to Pointers

#define SIZE 50

int x[SIZE];

int y[SIZE];

int I;

int *p1, *p2;

Now letʹs rewrite the function with pointers.

void

try2()

{

for( p1 = x, p2 = y; p1 – x < SIZE; )

*p1++ = *p2++;

}

Iʹve replaced the subscripts with pointer variables. One of the pointers is tested to determine when to exit the loop, so the counter is no longer needed.

我用指针变量取代了下标。其中一个指针用于测试,判断何时退出循环,所以这个方案不再需要计数器。



These changes do not give much of an improvement over the first version. The code needed to copy an integer and increment the pointers has decreased, but the initialization code has increased. The shifts to scale the subscript are gone, and the movl instruction that does the real work no longer uses indexing. But the code to check for the end of the loop has increased a lot, because the subtraction of two pointers must be scaled (in this case, divided by 4). The division is performed by pushing the values on the stack and calling a subroutine named ldiv. If this machine had a 32‐bit divide instruction, the division might have been done more efficiently.

和第1 个版本相比,这些变化并没有带来多大的改进。需要复制整数并增加指针值的代码减少了,但初始化代码却增加了。用于代替乘法的移位指令不见了,而且执行真正任务的movl 指令不再使用索引。但是,用于检查循环结束的代码却增加了许多,因为两个指令相减的结果必须进行调整(在这里是除以4)。除法运算是通过把值压到堆栈上并调用子程序ldiv 实现的。如果这台机器具有32 位除法指令,除法运算可能会完成得更有效率。


Bringing Back the Counter

Letʹs try another approach

void

try3()

{

for( i = 0, p1 = x, p2 = y; i < SIZE; i++ )

*p1++ = *p2++;

}

Iʹve used the counter again to control when the loop should exit to get rid of the pointer subtraction and the resulting long sequence of code.

我重新使用了计数器,用于控制循环何时退出,这样可以去除指针减法,并因此缩短目标代码的长度。



This version has the shorter code to copy the integer and increment the pointers, and to control when the loop breaks. But weʹre still copying the pointer variables into address registers before the indirection.

在这个版本中,用于复制整数和增加指针值以及控制循环结束的代码要短一些。但在执行间接访问之前,我们仍需把指针变量复制到地址寄存器。


Register Pointer Variables

We can eliminate copying the pointer values by using register variables for the pointers. However, they must be declared as local variables.

我们可以对指针使用寄存器变量,这样就不必复制指针值。但是,它们必须被声明为局部变量。

void

try4()

{

register int *p1, *p2;

register int i;

for( i = 0, p1 = x, p2 = y; i < SIZE; i++ )

*p1++ = *p2++;

}

This change improves more than just eliminating the copying of the pointers.

这个变化带来了较多的改进,并不仅仅是消除了复制指针的过程。


Note that the pointer variable exist in registers a4 and a5 from the start. We can increment them directly with the hardwareʹs autoincrement addressing mode (which behaves very much like the C postfix ++ operator). The initialization and loop termination code is, for the most part, unchanged. This code is looking better.

注意,指针变量一开始就保存于寄存器a4 和a5 中,我们可以使用硬件的地址自动增量模型(这个行为非常像C 的后缀++操作符)直接增加它们的值。初始化和用于终止循环的代码基本未作变动。这个版本的代码看上去更好一些。


Eliminating the Counter

If we can find a way to terminate the loop without using the pointer subtraction that caused trouble earlier, we can eliminate the counter.

如果我们能找到一种方法来判断循环是否终止,但并不使用开始所提到的那种会引起麻烦的指针减法,我们就可以消除计数器。


void

try5()

{

register int *p1, *p2;

for( p1 = x, p2 = y, p1 < &x[SIZE]; )

*p1++ = *p2++;

}


Instead of the subtraction to see now many elements weʹve copied, this loop checks to see whether the pointer p1 has reached the end of the source array. Functionally this test is just as good, but it should be more efficient because it does not do a subtraction.Furthermore, the expression &x[SIZE] can be evaluated at compile time, because SIZE is a literal constant. Here is the result.

这个循环并没有使用指针减法来判断已经复制了多少个元素,而是进行测试,看看pl 是否到达源数组的末尾。从功能上说,这个测试应该和前面的一样,但它的效率应该更高,因为它不必执行减法运算。而且,表达式&x[SIZE] 可以在编译时求值,因为SIZE 是个数字常量。下面是它的结果:


This code is compact and fast and rivals what an assembly language programmer would have produced. The counter and its associated instructions are gone. The comparison instruction contains the expression _x+200, which is the expression &x[SIZE]. This computation was done at compile time because SIZE is a constant. This code is about as tight as we can get on this machine.

这个版本的代码非常紧凑,速度也很快,完全可以与汇编程序员所编写的同类程序相媲美。计数器以及相关的指令不见了。比较指令包含了表达式_x+200 ,也就是源代码中的&x[SIZE] 。由于SIZE是个常量,所以这个计算可以在编译时完成。这个版本的代码是我们在这个机器上所能获得的最紧凑的代码。


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

Chapter 1 Chapter 2 Chapter 3 Chapter 4 Chapter 5 Chapter 6 Chapter 7 Chapter 8 Chapter 9 Chapter 10 Chapter 11 Chapter 12 Chapter 13 Chapter 14 Chapter 15 Chapter 16 Chapter 17 Chapter 18 Contents A Quick Start ........................................................................................................ 1 Basic Concepts ...................................................................................................... 7 Data ....................................................................................................................... 11 Statements ............................................................................................................. 15 Operators and Expressions .................................................................................... 23 Pointers .................................................................................................................. 29 Functions ............................................................................................................... 37 Arrays .................................................................................................................... 43 Strings, Characters, and Bytes .............................................................................. 55 Structures and Unions ........................................................................................... 69 Dynamic Memory Allocation ................................................................................ 75 Using Structures and Pointers ............................................................................... 79 Advanced Pointer Topics ...................................................................................... 87 The Preprocessor ................................................................................................... 93 Input/Output Functions .......................................................................................... 95 Standard Library .................................................................................................... 119 Classic Abstract Data Types ................................................................................. 129 Runtime Environment ........................................................................................... 145
Pointers On C brings the power of pointers to your C programs. Designed for professionals and advanced students, Pointers on C provides a comprehensive resource for those needing in-depth coverage of the C programming language. An extensive explanation of pointer basics and a thorough exploration of their advanced features allows programmers to incorporate the power of pointers into their C programs. Complete coverage, detailed explanations of C programming idioms, and thorough discussion of advanced topics makes Pointers on C a valuable tutorial and reference for students and professionals alike. Features and Benefits Provides complete background information needed for a thorough understanding of C. Covers pointers thoroughly, including syntax, techniques for their effective use and common programming idioms in which they appear. Compares different methods for implementing common abstract data structures. Offers an easy, conversant writing style to clearly explain difficult topics, and contains numerous illustrations and diagrams to help visualize complex concepts. Includes Programming Tips, discussing efficiency, portability, and software engineering issues, and warns of common pitfalls using Caution! Sections. Describes every function on the standard C library. For those who need an up-to-date ANSI overview of the C programming language, this book would be an excellent introduction. Pointers are usually a stumbling block for those programming C initially, but the author does an excellent job of detailing the use of pointers in this book. The use of pointers dominates the entire book, and after studying it, readers will have a thorough, practical knowledge of how to take advantage of the performance power of C language, due mostly to its use of pointers. For those programming in a commercial/business environment, where coding practices are strictly enforced, this book would be a good desk reference, as the author includes discussion of sound programming practices throughout the book. The book would also serve well those involved in teaching C in the classroom, as it contains many exercises, ranging from very easy to highly advanced. And for those readers frequently facing legacy code in C, such as scientific programmers, the author cites the differences between the older "Kernighan-Ritchie" C, and the more modern ANSI C, the latter being used in the book. These differences are indicated in the margin of the book, and are of an enormous help for those who must take older code and get it to run on more up-to-date compilers. The author also endeavors to organize the C code for those who are going on to study C++ and the accompanying object-oriented approach to programming. In addition, he emphasizes how to write C code so as to make it more portable. For those writing commercial applications in C that must be used on different platforms, this is a very important issue of course. Particularly well-written is the author's discussion on the storage class of a variable, noting, for those such as I who are pre-disposed to using recursion, that the formal parameters to a function cannot be static if recursion is to be supported. The book is full of examples such as this that give readers insight on the workings of C that fit their particular programming style. He does discuss `goto' statements in relation to function scope and in C statement structures, but, thankfully, recommends such statements never be used. He gives an interesting counterexample to those who say that goto statements must be used to break out of nested loops. Also, the author discusses the difference between L- and R-values, and this is not usually included in beginning books on C. Dynamic memory allocation has been at times a somewhat painful aspect of programming in C, but the author shows how to do straightforwardly in the book. Having a book like this that is predominantly about pointers is quite a blessing for those who are inexperienced with them or for more experienced programmers who are still uncomfortable with their use. It is not uncommon these days to have to write programs in one's professional work that involve triple pointers or even quadruple pointers. In addition, for embedded systems programming, the use of pointer arithmetic is almost mandatory. This also is true for writing applications in cryptography using C. The author does pay careful attention to pointer arithmetic in the book. The performance pay-off for using pointers is undeniable, and so a thorough knowledge of their use and pit-falls is of upmost importance for those C programmers who are involved in writing performance-sensitive applications. The author discusses in detail what can happen when pointers are misused and gives many examples of what to avoid and good hints for the proper use of pointers. He recommends against the use of the `null' pointer in array searching, and recommends a strategy for circumventing them. Some very helpful diagrams are given for explaining pointer expressions. In addition, the author gives helpful hints on when to use pointers and not subscripts when manipulating arrays in C. The performance issues involved in this are extremely important in scientific programming using C. The author gives a very interesting example of the differences in performance using pointers involving a program to copy the contents of one array into another. Arrays of pointers, useful in data mining applications, are also given ample treatment in this book, and the author addresses the issue of when to use a matrix instead of an array of pointers. The author also gives an effective presentation of functions in C, particularly the construction of recursive functions, and he employs some useful diagrams to illustrate how the variables in a recursive function call change on the stack. The performance hit experienced by using recursion versus iterative loops is discussed in a standard way via the Fibonacci series. Those readers raised in the functional programming paradigm will want to pay notice these performance issues when using C to do recursion. Along the same lines, the author shows how to implement functions with variable argument lists in C. This is another topic that is frequently passed over in beginning books on C. The author's treatment of data structures in C is also very nicely done, and he includes again a topic not usually treated in beginning books on C, namely the concept of a self-referential data structure. These are very important in applications in artificial intelligence, and the author shows how to implement them in C using a data structure that points to itself. This leads to a discussion of incomplete declarations. Very helpful diagrams are used again to discuss how to access members of data structures and how to point to data structures. Bit fields, so often used in embedded system applications, are also given a detailed treatment.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值