Pointer and addresses -- C calls swap

--- A side note. Both Fortran and C pass 1 dimensional arrays in the same way a[1] is the address of the array in C, just as A[1] is in Fortran. ---

First a bit about pointers and addresses based on Chapter 5 of K&R

         p=&c

assigns the address of c to the integer p which is said to "point to" c.

         The unitary operator * is the indirection or dereferencing operator. When applied to a pointer, it accesses the object the pointer points to. cpp\panda.c

#include <stdio.h>
main()
{int ix=1,iy=2;
int *ip; /* ip is a pointer to an integer */
ip=&ix; /* ip now contains the address of ix */
iy=*ip; /* iy is now equal to the value in the address in ip */
printf(" ix,iy %d %d \n",ix,iy);
return 0;}

 

running the above code produces

ix,iy 1 1

Note that the type of variable that the pointer points to needs to be defined in its definition even though it is actually always an integer address. This comes about because of the "dereferencing" step when it is converted back into an actual value.

         Make a subroutine out of this cpp\swap.c

 

void swap_(int *ix,int *iy) /the underscore will be useful for Fortran/
{ int it;
it=*ix;
*ix=*iy;
*iy=it;
printf("from swap ix,iy %d %d \n",ix,iy);
printf("from swap *ix,*iy %d %d \n",*ix,*iy);
return;}

 

The following example uses this subroutine to swap the values of ix and iy. cpp\ccswap.c

 

#include <stdio.h>

void swap_(int *ix,int *iy);

#include "swap.c"

main()

 {int ix=1,iy=2;

  int *ip,*iq; /* ip and iq are pointers to integers */

  ip=&ix; /* ip now contains the address of ix */
  iq=&iy; /* iq now contains the address of iy */
  swap_(ip,iq); 
  printf(" ix,iy %d %d \n",ix,iy);
  return 0;}

 which produces

from swap ix,iy 6618624 6618620 the addresses of ix,iy
from swap *ix,*iy 2 1 the values in these addresses
ix,iy 2 1 the main code swapped results

Fortran calls swap

The Fortran version of the swap subroutine is for\swap.for

      SUBROUTINE SWAP(IX,IY)
      IT=IX
      IX=IY
      IY=IT
      RETURN
      END

Note that the watfor editor may have trouble reading files fron a Unix system. Use the dos edit, change one item and change it back. Then save the file. From here on watfor can read the file. The calling routine is for\fcswap.FOR

From the e editor

<beginning of file>
DATA IX,IY/1,2/
CALL SWAP(IX,IY)
PRINT*,' IX,IY ',IX,IY
END
C$INCLUDE SWAP
<end of file>
 
fcswap.for - Lines transferred = 5
run
IX,IY 2 1 <hold>

     Note that I am unable to print out the addresses in the Fortran swap routine.

 

 

Fortran calls C

The variable that Fortran calls IX is &IX in C

Use the C swap routine and the Fortran calling routine

I tested this with

 cc -c swap.c

f77 fcallc.f swap.o

 

ligo[Progdet/cpp] a.out
from swap ix,iy 155204 155208
from swap *ix,*iy 2 1
IX,IY 2 1
ligo[Progdet/cpp]

C calls Fortran

         The Fortran routine is

      SUBROUTINE SWAP(IX,IY)
      PRINT*,' FROM SWAP ENTER WITH IX,IY=',IX,IY
      IT=IX
      IX=IY
      IY=IT
      PRINT*,' FROM SWAP LEAVE WITH IX,IY=',IX,IY
      RETURN
      END

 

With an extra print. The ccallf is the routine above

 
ligo[Progdet/cpp] f77 -c swap.f
swap.f:
swap:
ligo[Progdet/cpp] cc -c ccallf.c
ligo[Progdet/cpp] f77 ccallf.o swap.o
ligo[Progdet/cpp]
 
ligo[Progdet/cpp] a.out
FROM SWAP ENTER WITH IX,IY= 1 2
FROM SWAP LEAVE WITH IX,IY= 2 1
ix,iy 2 1

Static variable nc

#include <stdio.h>
void swap_(int *ix,int *iy);
#include "swap2.c"
main()
{int ix=1,iy=2;
int *ip,*iq; 
ip=&ix;
iq=&iy; 
swap_(ip,iq);
swap_(ip,iq);
printf(" ix,iy %d %d \n",ix,iy);
return 0;}

 

void swap_(int *ix,int *iy)
{ int it;
static int nc=0;
printf("from swap nc=%d\n",nc);
nc=1;
it=*ix;
*ix=*iy;
*iy=it;
printf("from swap ix,iy %d %d \n",ix,iy);
printf("from swap *ix,*iy %d %d \n",*ix,*iy);
return;}

 

ligo[Progdet/cpp] cc ccswap.c
ligo[Progdet/cpp] a.out
from swap nc=0
from swap ix,iy -268437304 -268437308
from swap *ix,*iy 2 1
from swap nc=1
from swap ix,iy -268437304 -268437308
from swap *ix,*iy 1 2
ix,iy 1 2
ligo[Progdet/cpp]

 

Fortran variable nc

for\FUNCT.FOR

FUNCTION FUN1(CP)
IMPLICIT REAL*8 (A-H,O-Z)
CHARACTER*128 NAME
DIMENSION CP(4)
SAVE NC,A,B,C,D
DATA NC/0/
IF(NC.EQ.0)THEN
PRINT*,'ENTER THE FILE NAME WITH A,B,C'
READ(*,'(A)')NAME
OPEN(1,FILE=NAME)
READ(1,*)A,B,C,D
CLOSE(1)
NC=1
ENDIF
FUN1=(A-CP(1))**2+(B-CP(2))**2+(C-CP(3))**2+(D-CP(4))**2
RETURN
END
 

The test code for this is for\TEST.FOR

 
IMPLICIT REAL*8 (A-H,O-Z)
DIMENSION C(4)
5 PRINT*,' ENTER C'
READ(*,*)C
IF(C(1).EQ.-1D0)STOP
TEST=FUN1(C)
PRINT*,' TEST=',TEST
GOTO 5
END
C$INCLUDE FUNCT
 

From watfor issue the command

RUN /EXE

*WRN* ST-09 line 9, this statement will never be executed due to the preceding branch

 

>TEST
ENTER C
1 2 3 4
ENTER THE FILE NAME WITH A,B,C
ABCD.IN
TEST= 13809.000000000000000
ENTER C
5 6 7 8
TEST= 12425.000000000000000
ENTER C
-1 0 0 0

C opening a file from a subroutine

      The subroutine is cpp\funct.c
double funct(double cp[4])
{FILE *fp;
 char name[128];
 static int nc=0;
 static double a,b,c,d;
 double temp,temps;
 if(nc == 0)
  {printf(" enter the data file name\n");
   scanf("%s",name);
   if((fp=fopen(name,"r"))==NULL)
     {printf(" cannot open file\n");
      scanf("%d",nc);
      return -1000.;}
 fscanf(fp,"%lg %lg %lg %lg",&a,&b,&c,&d);
 fclose(fp);
 nc=1;}
 temp=(a-cp[1]);
 temps=temp*temp;
 temp=(b-cp[2]);
 temps+=temp*temp;
 temp=(c-cp[3]);
 temps+=temp*temp;
 temp=(d-cp[4]);
 temps+=temp*temp;
 return temps;}
 

The test routine is cpp\test.c

>bcc32 test.c
Borland C++ 5.2 for Win32 Copyright (c) 1993, 
 
>test
enter c(1) to c(4), c(1)=-1000 to exit1 2 3 4
1 2 3 4 enter the data file name
abcd.in
ft = 13809
enter c(1) to c(4), c(1)=-1000 to exit5 6 7 8
5 6 7 8 ft = 12425
enter c(1) to c(4), c(1)=-1000 to exit-1000 0 0 0
-1000 0 0 0
>