Share via


Character Strings

In Win32, Fortran by default passes a hidden length argument for strings. This argument is easily accessible to other languages, unlike the string-length information passed in 16-bit versions of Fortran. The hidden length argument consists of an unsigned 4-byte integer, always passed by value, immediately following the character string argument.

For example, if a Fortran program sets up the following call to a routine, Pass_Str, implemented in C:

      INTERFACE TO SUBROUTINE Pass_Str (string)
      CHARACTER*(*) string
      END

Then the C routine must expect two arguments:

void __stdcall PASS_STR (char *string, unsigned int length_arg )

Another important difference is in the format of the strings themselves. C strings are null-terminated. For example, given the following assignment:

Char *cstring="C text string";

The string data is stored as shown in the following figure.

Fortran strings are not null-terminated, and they are padded with blank spaces when assigned string data that is shorter than the declared length. For example, given the following assignment:

      CHARACTER*14 forstring
      DATA FORSTRING /"Fortran STRING'/

The string data is stored as follows. Note that if the string were any longer, it would be padded with trailing blanks.

A more efficient approach, wherever possible, is to adopt C string behavior. When the C or STDCALL attribute is applied to a routine, Fortran does not pass a hidden length argument. Furthermore, you can use the C-string feature to assign null-terminated string data in Fortran, as follows:

      CHARACTER*20 forstring
      DATA forstring /'This is a string'C/

The string variable, forstring, can then be passed to a C routine. If the C or STDCALL attribute is used, Fortran passes forstring just as C does: pushing the address of a null-terminated string onto the stack, with no hidden length argument.

Note   Fortran functions of type CHARACTER*(*) place a hidden string argument at the beginning of the parameter list; this may include both string address and length, as appropriate. C functions that implement such a call from Fortran must declare this hidden string argument explicitly and use it to return a value. However, you are more likely to avoid errors by not using character-string return types. Use subroutines whenever possible.

The following example demonstrates how a Fortran main program calls a C function that translates a string to all-uppercase. Because the string is passed by reference, there is no need to use a string return type. Note that the C attribute stops Fortran from passing a hidden string-length argument, and the DATA statement uses a ā€œCā€ to specify null termination.

C    File FORMAIN.FOR
C
      INTERFACE TO SUBROUTINE Ucase [C,ALIAS:'_Ucase'] (text)
      CHARACTER*(*) text [REFERENCE]
      END

      CHARACTER*40 forstring
      DATA forstring /'This is a sample string.'C/
      WRITE (*, *) forstring
      CALL Ucase (forstring)
      WRITE (*, *) forstring
      END

/*     File CSTR.C   */

#include <ctype.h>

void Ucase( char *string )
{
    char *ptr;

    for (ptr = string; *ptr; ptr++)
        *ptr = toupper( *ptr );
}

This use of C strings is usually the best approach, because most C library functions, as well as API functions, assume null-termination. However, if you use C to write string-manipulation functions, it is a good idea to translate null-terminated strings back into blank-padded strings after the C function returns. The following code performs this operation:

      SUBROUTINE Fix_C_Str (text, length)
      CHARACTER*(*) text
      INTEGER*4 length

      INTEGER*4 i

C  Find the first null ('\0')

      i = 1
      DO WHILE ((i .LE. length) .AND. (text(i:i) .NE. '\0'))
        i = i + 1
      END DO

C  Pad with blanks to the end of the string

      DO WHILE (i .LE. length)
        text (i:i) = ' '
      END DO
      END