interesting discussion of differences between C and Fortran from sci.math.num-analysis

Thomas M. Breuel uunet!ai.mit.edu!tmb
Sat Aug 24 14:10:38 PDT 1991


|1.  Consider the example originally from Jim Giles in an earlier thread: 
|
|      subroutine copyit(a,b,n)              void copyit(a,b,n)
|      integer n                             int n;
|      real a(n), b(n)                       float *a, *b;
|      integer i, p, q                       {
|                                               float *z; int p, q;
|      p = irtc()                               p = _rtc();
|      do i=1,n
|         a(i) = b(i)                           for(z=a; z<a+n; *z++ = *b++);
|      enddo
|   1  a(1) = a(n)                              a[0] = a[n-1];
|      q = irtc()                               q = _rtc();
|      print *, q-p                             printf("%d\n",q-p);
|      end                                   }
|[...]
|Unfortunately, there is no way, within Standard C, to write copyit so that
|it may be used only to copy between disjoint objects:  You must pay for
|the full generality whether you need it or not.

That is not entirely true. In fact, there are several ways of
expressing the function so that a smart compiler could infer
absence of aliasing:

void copyit_1(float *a,const float *b,int n) {
	while(--n>=0) a[n]=b[n];
}

float *copyit_2(float *b,int n) {
	float *a=malloc(n * sizeof *a);
	while(--n>=0) a[n]=b[n];
	return a;
}

void copyit_3(a,b,n) float *a,*b; {

	/* NB: invalid in ANSI-C because a and b might not 
	   be "from the same array" */

	ASSERT(labs(a-b)<n);
	while(--n>=0) a[n]=b[n];
}

(BTW, looking at JLG's original code: I think it is better
not to convert from index notation to pointer arithmetic by 
hand. Also, it is usually better to choose a constant in
the termination condition, since that frees a register; so,
on many machines, it's better to count towards "0", not 
towards "n", although in this case, the compiler could
reverse the loop automatically.)

|The most recent release, 3.0, also offers a language extension that
|enables you to write copyit so that it has the same restriction as in
|Fortran:  it may be used only to copy between disjoint objects.  If you
|are willing to modify the source code, you can change the declarations of
|the parameters to read:
|
|		float * restrict a, * restrict b;
|
|Here 'restrict' is a type qualifier, and the compiler may assume that a
|pointer of restrict-qualified type points into a unique object (as if it
|obtained its value from a call to malloc).

It would be better to let the programmer assert absence of 
aliasing between specific pointers explicitly (as in copyit_3),
rather than letting the programmer assert "this pointer is not
aliased with anything". To help the programmer, the compiler can
warn (when asked) about pairs of pointers whose aliasing status
is unknown and which are inhibiting optimization.

"restrict" may be a good way of appeasing FORTRAN programmers who 
have to switch to C, but I think it is poor language design (if
you care to know, I can give you a more extensive discussion of
why I think it's not a good idea).

|  Variable length arrays.
|    (analogous to Fortran adjustable and automatic arrays)

BTW, GNU CC has had variable length arrays for quite some time.

					Thomas.



More information about the Numeric-interest mailing list