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[1]

            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

>



[1]B.W. Kernighan and D.M. Ritchie, The C programming Language (second edition), Prentice Hall (1988) p.93