Está en la página 1de 122

MATEMÁTICAS NUMÉRICAS Y COMPUTACIÓN CIENTÍFICA

Editores de serie
AM STUART E. SÜLI
EBSCO Publishing: eBook Collection (EBSCOhost) - impreso el 3/1/2019 9:18 AM a través de MICHIGAN STATE UNIV

Página 3
MATEMÁTICAS NUMÉRICAS Y COMPUTACIÓN CIENTÍFICA
Libros de la serie
Las monografías marcadas con un asterisco (*) aparecieron en la serie 'Monografías en análisis numérico', que es
Continuado por la serie actual.
Para obtener una lista completa de títulos, visite
https://global.oup.com/academic/content/series/n/numerical-mathematics-and-scientific-computation-nmsc/?lang=
* JH Wilkinson: el problema del valor propio algebraico
* I. Duff, A. Erisman y J. Reid: Métodos directos para matrices dispersas
* MJ Baines: elementos finitos en movimiento
* JD Pryce: solución numérica de problemas de Sturm-Liouville
C. Schwab: p- y hp- Métodos de elementos finitos: teoría y aplicaciones en mecánica de sólidos y fluidos
JW Jerome: Modelado y Computación para Aplicaciones en Matemáticas, Ciencias e Ingeniería
A. Quarteroni y A. Valli: Métodos de descomposición de dominio para ecuaciones diferenciales parciales
G. Em Karniadakis y SJ Sherwin: Métodos de elementos espectrales / hp para dinámica de fluidos computacional
I. Babuška y T. Strouboulis: el método de elementos finitos y su fiabilidad
B. Mohammadi y O. Pironneau: optimización de forma aplicada para fluidos
S. Succi: la ecuación de Boltzmann de celosía para la dinámica de fluidos y más allá
P. Monk: métodos de elementos finitos para las ecuaciones de Maxwell
A. Bellen y M. Zennaro: métodos numéricos para ecuaciones diferenciales de retardo
J. Modersitzki: métodos numéricos para el registro de imágenes
M. Feistauer, J. Felcman e I. Straškraba: métodos matemáticos y computacionales para flujo compresible
W. Gautschi: polinomios ortogonales: cálculo y aproximación
MK Ng: Métodos iterativos para sistemas Toeplitz
M. Metcalf, J. Reid y M. Cohen: Fortran 95/2003 explicado
G. Em Karniadakis y S. Sherwin: métodos de elementos espectrales / hp para dinámica de fluidos computacional ,
Segunda edicion
DA Bini, G. Latouche y B. Meini: métodos numéricos para cadenas de Markov estructuradas
H. Elman, D. Silvester y A. Wathen: elementos finitos y solucionadores iterativos rápidos: con aplicaciones
en dinámica de fluidos incompresible
M. Chu y G. Golub: problemas de valores propios inversos: teoría, algoritmos y aplicaciones
J.-F. Gerbeau, C. Le Bris y T. Lelièvre: Métodos matemáticos para la magnetohidrodinámica de metales líquidos
G. Allaire y A. Craig: Análisis numérico y optimización: una introducción al modelado matemático y
Simulación numérica
K. Urban: Métodos Wavelet para ecuaciones diferenciales parciales elípticas
B. Mohammadi y O. Pironneau: Optimización de forma aplicada para fluidos, segunda edición
K. Boehmer: métodos numéricos para ecuaciones diferenciales elípticas no lineales: una sinopsis
M. Metcalf, J. Reid y M. Cohen: Modern Fortran explicado
J. Liesen y Z. Strakoš: Métodos del subespacio de Krylov: principios y análisis
R. Verfürth: técnicas de estimación de errores a posteriori para métodos de elementos finitos
H. Elman, D. Silvester y A. Wathen: elementos finitos y solucionadores iterativos rápidos: con aplicaciones en
Dinámica de fluidos incompatibles , segunda edición
I. Duff, A. Erisman y J. Reid: Métodos directos para matrices dispersas , segunda edición
M. Metcalf, J. Reid y M. Cohen: Modern Fortran Explained , Second Edition
es & cc = cn
EBSCO Publishing: eBook Collection (EBSCOhost) - impreso el 3/1/2019 9:18 AM a través de MICHIGAN STATE UNIV

Página 4

Fortran moderno explicado


Michael Metcalf, John Reid y Malcolm Cohen

1
Incorporando Fortran 2018
EBSCO Publishing: eBook Collection (EBSCOhost) - impreso el 3/1/2019 9:18 AM a través de MICHIGAN STATE UNIV

Página 5
3
Gran calle Clarendon, Oxford, OX2 6DP,
Reino Unido
Oxford University Press es un departamento de la Universidad de Oxford.
Fomenta el objetivo de excelencia de la Universidad en investigación, investigación,
y educación publicando en todo el mundo. Oxford es una marca registrada de
Oxford University Press en el Reino Unido y en otros países.
c G Michael Metcalf, John Reid y Malcolm Cohen 2018
Se han afirmado los derechos morales de los autores.
Primera edición publicada en 1987 como Fortran 8x Explicado
Segunda edición publicada 1989
Tercera edición publicada en 1990 como Fortran 90 Explicado
Cuarta edición publicada en 1996 como Fortran 90/95 explicada
Quinta edición publicada 1999
Sexta edición publicada en 2004 como Fortran 95/2003 explicada
Séptima edición publicada 2011 como Modern Fortran Explained
Esta edición publicada 2018
Impresión: 1
Todos los derechos reservados. Ninguna parte de esta publicación puede ser reproducida, almacenada en
un sistema de recuperación, o transmitido, en cualquier forma o por cualquier medio, sin el
permiso previo por escrito de Oxford University Press, o según lo expresamente permitido
por ley, por licencia o bajo los términos acordados con la reprografía apropiada
organización de derechos. Consultas sobre reproducción fuera del alcance de la
arriba debe enviarse al Departamento de Derechos, Oxford University Press, en el
dirección arriba
No debe circular este trabajo de ninguna otra forma.
y debe imponer esta misma condición a cualquier adquirente
Publicado en los Estados Unidos de América por Oxford University Press
198 Madison Avenue, Nueva York, NY 10016, Estados Unidos de América
Catalogación de la Biblioteca Británica en los datos de publicación
Datos disponibles
Número de control de la Biblioteca del Congreso: 2018947662
ISBN 978–0–19–881189–3 (hbk.)
ISBN 978–0–19–881188–6 (pbk.)
DOI 10.1093 / oso / 9780198811886.001.0001
Impreso y encuadernado por
CPI Group (UK) Ltd, Croydon, CR0 4YY
EBSCO Publishing: eBook Collection (EBSCOhost) - impreso el 3/1/2019 9:18 AM a través de MICHIGAN STATE UNIV

Página 6

Prefacio
Fortran sigue siendo uno de los principales idiomas utilizados en los campos de la ciencia, la numérica,
y programación de ingeniería, y una serie de revisiones al estándar que define sucesivamente
versiones del lenguaje han mejorado progresivamente su poder y lo han mantenido competitivo con
Varias generaciones de rivales.
A partir de 1978, el comité técnico responsable del desarrollo de Fortran
estándares, X3J3 (ahora PL22.3 pero aún informalmente llamado J3), trabajaron para producir un nuevo
necesitaba una versión moderna del lenguaje, Fortran 90. Su propósito era 'promover la portabilidad,
fiabilidad, mantenibilidad y ejecución eficiente ... en una variedad de sistemas informáticos '.
Ese estándar fue publicado en 1991, y el trabajo comenzó en 1993 en una revisión menor, conocida como
Fortran 95. Posteriormente, y con el mismo propósito, una actualización importante del idioma
fue preparado por J3 y el comité internacional, WG5. Esa revisión, que incluía
características de programación orientada a objetos, ahora se conoce como Fortran 2003. Esto fue seguido
por una nueva revisión, Fortran 2008, que incluye matrices de arrays; y, más recientemente, una revisión menor,
Fortran 2018, que incluye más funciones de coarray. Una vez más, hemos preparado un definitivo
Descripción informal del lenguaje que define este último estándar. Esto continua la serie
de ediciones de este libro: las dos ediciones de Fortran 8x explicadas que describen
borradores de la norma (1987 y 1989), Fortran 90 explicado que describe el Fortran 90
estándar (1990), dos ediciones de Fortran 90/95 explicadas que incluían también Fortran 95
(1996 y 1999) y Fortran 95/2003 (2004), con sus capítulos adicionales sobre Fortran 2003. En
En ese esfuerzo, un tercer coautor fue bienvenido. Finalmente, la primera edición de Modern Fortran
Explicado (2011) agregó más capítulos sobre Fortran 2008.
En esta edición, el lenguaje básico es Fortran 2008. Un capítulo inicial establece los antecedentes.
al trabajo sobre nuevos estándares, y los capítulos 2 a 19 describen Fortran 2008 de una manera
adecuado tanto para comprender las implicaciones de sus características como para escribir programas. los
Los capítulos restantes describen las características adicionales de Fortran 2018. Algunos conocimientos de
Se asume conceptos de programación. Para reducir el número de referencias directas y
también para permitir, lo más rápido posible, que se escriban programas útiles basados en material ya
absorbido, el orden de presentación no siempre sigue el del estándar. En particular,
hemos optado por diferir a los apéndices la descripción de las características que están oficialmente etiquetadas
como redundante (algunos de los cuales fueron eliminados del estándar) y otras características cuyo uso
nosotros despreciamos Pueden encontrarse en programas antiguos, pero no son necesarios en los nuevos.
Tenga en cuenta que, además de un pequeño número de eliminaciones, cada uno de los idiomas Fortran 77,
Fortran 90, Fortran 95, Fortran 2003, Fortran 2008 y Fortran 2018 es un subconjunto de sus
sucesor.

Página 7
vi Prefacio
Para que el libro sea un trabajo de referencia completo, concluye con cuatro apéndices.
Contienen, sucesivamente, una descripción de varias características cuyo uso despreciamos y
no describa en el cuerpo del libro, una descripción de características obsoletas y eliminadas,
Un ejemplo extendido que ilustra el uso de la orientación a objetos y soluciones a la mayoría de
ejercicios.
Esperamos que este libro, al proporcionar descripciones completas de Fortran 2008 y
Fortran 2018, continuará el papel útil que jugaron las ediciones anteriores para el correspondiente
versiones del estándar, y que servirá como un trabajo de referencia a largo plazo para los modernos
Fortran lenguaje de programación.

Página 8

Las convenciones usadas en este libro


..
El texto que se muestra en Fortran está configurado en fuente de máquina de escribir:
entero :: i, j
Una línea que consta de puntos verticales (...):
ordenamiento de subrutinas
.
fin de la subrutina
indica líneas omitidas y puntos suspensivos (...):
data_distance = ...
indica código omitido.
Los términos informales de BNF están en cursiva:
if (scalar-logical-expr) action-stmt
Los corchetes en cursiva indican elementos opcionales:
finalizar si [nombre]
y una elipsis representa un número arbitrario de elementos repetidos:
[selector de caso [nombre]]
bloque] ...
La letra cursiva b significa un carácter en blanco.
Las correcciones a cualquier error significativo detectado en este libro estarán disponibles en el archivo
edits.pdf en ftp://ftp.numerical.rl.ac.uk/pub/MRandC.

Página 9

Página 10

Contenido
1 ¿De dónde viene Fortran?
1
1.1
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1,2
Fortran'searlyhistory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3
El impulso para el estándar Fortran 90 . . . . . . . . . . . . . . . . . . . . . 2
1.4
Evolución del lenguaje. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1,5
Fortran95. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4
1.6
Extensiones a Fortran95. . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5
1.7
Fortran2003. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5
1,8
Extensiones a Fortran 2003 . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6
1.9
Fortran2008. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6
1.10 Extensiones a Fortran2008. . . . . . . . . . . . . . . . . . . . . . . . . . . 7 7
1.11 Fortran2018. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 7
1.12 Conformidad. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 7
2 elementos del lenguaje
99
2.1
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9
2.2 2.2
Fortrancharacterset. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9
2.3
Fichas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2,4
Forma de origen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.5
Conceptoftype. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.6
Constantes literales de tipo intrínseco . . . . . . . . . . . . . . . . . . . . . . . 13
2.6.1
Constantes literales . . . . . . . . . . . . . . . . . . . . . . . . 14
2.6.2
Constantes reales . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.6.3
Constantes literales complejas. . . . . . . . . . . . . . . . . . . . . . . dieciséis
2.6.4
Constantes literales de caracteres . . . . . . . . . . . . . . . . . . . . . . . dieciséis
2.6.5
Constantes lógicas literales . . . . . . . . . . . . . . . . . . . . . . . . 18 años
2.6.6
Constantes binarias, octales y hexadecimales . . . . . . . . . . . . . . . 19
2.7
Nombres. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.8
Variables escalares de tipo intrínseco . . . . . . . . . . . . . . . . . . . . . . . . 20
2.9
Tipos de datos derivados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.10 Arraysofintrinsictype. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.10.1 Declaringentitiesofdifferingshapes. . . . . . . . . . . . . . . . . 25
2.10.2 Objetos asignables. . . . . . . . . . . . . . . . . . . . . . . . . . 25

Página 11
x Contenido
2.11 Subcadenas de caracteres. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.12 Punteros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.13 Objetos y objetos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.14 Resumen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3 Expresiones y asignaciones
33
3.1
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.2
Expresiones escalarnuméricas. . . . . . . . . . . . . . . . . . . . . . . . . . 34
3,3
Variables definidas e indefinidas . . . . . . . . . . . . . . . . . . . . . . . . 37
3.4
Asignación numérica escalar. . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.5
Operadores escalar-relacionales. . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.6
Expresiones y asignaciones lógicas escalares . . . . . . . . . . . . . . . . . . 39
3.7
Asignaciones y expresiones de caracteres escalares . . . . . . . . . . . . . . . . . 40
3.7.1
Conjunto de caracteres ASCII. . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.7.2
Conjunto de caracteres ISO 10646 . . . . . . . . . . . . . . . . . . . . . . . . 42
3.8
Constructores de estructuras. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.9
Scalardefinedoperators. . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.10 Scalardefinedassignments. . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.11 Expresiones de arrays. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.12 Asignación de matriz. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.13 Indicadores de expresiones expresas y firmas. . . . . . . . . . . . . . . . . . . . 49
3.14 Luego, anule la declaración. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.15 Resumen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4 construcciones de control
55
4.1
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.2 4.2
Su construcción y declaración. . . . . . . . . . . . . . . . . . . . . . . . . 55
4.3 4.3
La construcción del caso. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.4
Thedoconstruct. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.5 4.5
Salga de casi cualquier construcción . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.6
Thegotostatement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.7
Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
5 Unidades y procedimientos del programa
69
5.1
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.2
Programa principal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
5.3
La declaración final. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
5.4
Subprogramas externos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
5.5
Módulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
5.6
Subprogramas internos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
5.7
Argumentos de procedimientos. . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
5.7.1
Conjuntos de formas asumidas. . . . . . . . . . . . . . . . . . . . . . . . . 78
5.7.2
Pointeargumentos. . . . . . . . . . . . . . . . . . . . . . . . . . . 78
5.7.3
Restricciones sobre argumentos reales. . . . . . . . . . . . . . . . . . . 79
5.7.4
Argumentos con el atributo de destino . . . . . . . . . . . . . . . . . . 80

Pagina 12
Contenidos xi
5.8
El estado de cuenta. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.9
Argumento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.10 Funciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
5.10.1 Efectos secundarios prohibidos. . . . . . . . . . . . . . . . . . . . . . . . . 83
5.11 Interfaces explícitas e implícitas. . . . . . . . . . . . . . . . . . . . . . . . . 83
5.11.1 La declaración de importación. . . . . . . . . . . . . . . . . . . . . . . . . 85
5.12 Procedimientos como argumentos. . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
5.13 Argumentos clave de la palabra clave. . . . . . . . . . . . . . . . . . . . . . . 88
5.14 Scopeoflabels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
5.15 Alcance de los nombres. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
5.16 Recursión directa. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
5.17 Recurrencia indirecta. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
5.18 Sobrecarga e interfaces genéricas. . . . . . . . . . . . . . . . . . . . . . 94
5.19 Longitud de caracteres asumida. . . . . . . . . . . . . . . . . . . . . . . . . . . 99
5.20 Las declaraciones de subrutina y función. . . . . . . . . . . . . . . . . . . . 99
5.21 Resumen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
6 Asignación de datos
105
6.1
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
6.2
El atributo asignable. . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
6.3
Parámetros de tipos diferidos. . . . . . . . . . . . . . . . . . . . . . . . . . . 106
6.4
Asignación de escalares. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
6.5
La asignación del enunciado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
6.6
La asignación de asignación. . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
6.7
Reasignación automática. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
6.8
Transferencia de una asignación. . . . . . . . . . . . . . . . . . . . . . . . . . . 110
6,9
Argumentos ficticios asignables. . . . . . . . . . . . . . . . . . . . . . . . . 111
6.10 Funciones asignables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
6.11 Componentes asignables. . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
6.11.1 Componentes asignables de tipo recursivo. . . . . . . . . . . . . . 115
6.12 Matrices asignablesvs. punteros . . . . . . . . . . . . . . . . . . . . . . . . 116
6.13 Resumen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
7 funciones de matriz
119
7.1
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
7.2
Rayos de tamaño cero. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
7.3
Objetos automáticos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
7.4
Operaciones elementales y tareas. . . . . . . . . . . . . . . . . . . . . 121
7.5
Funciones con valor de matriz. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
7.6
La declaración y la construcción where . . . . . . . . . . . . . . . . . . . . . . 123
7.7
Maskarrays. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
7.8
Procedimientos puros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
7,9
Procedimientos elementales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
7.10 Procedimientos elementales impuros. . . . . . . . . . . . . . . . . . . . . . . . . 128
7.11 Arrayelements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 129

Página 13
xii Contenido
7.12 Sujetos de matrices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
7.13 Arreglos de punteros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
7.14 Punterosasalias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
7.15 Pointeassignment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
7.16 Constructores de matrices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
7.17 La construcción simultánea. . . . . . . . . . . . . . . . . . . . . . . . . . 137
7.18 Características orientadas al rendimiento. . . . . . . . . . . . . . . . . . . . . . . . . 139
7.18.1 El atributo contiguo. . . . . . . . . . . . . . . . . . . . . . . . 139
7.18.2 Diseñadores de matriz simplemente contiguos. . . . . . . . . . . . . . . . . 142
7.18.3 Obtención automática de puntos por puntos. . . . . . . . . . . . . . . . . . . . . 144
7.19 Resumen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
8 declaraciones de especificación
149
8.1
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
8.2
Tipificación implícita. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
8.3
Constantes nombrados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
8.4
Expresiones constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
8.5
Valores iniciales para variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
8.5.1
Inicialización en declaraciones de declaración de tipo . . . . . . . . . . . . . . 153
8.5.2
La declaración de datos. . . . . . . . . . . . . . . . . . . . . . . . . . 154
8.5.3
Inicialización del puntero como disociada . . . . . . . . . . . . . . . . . 156
8.5.4
Inicialización del puntero como asociado . . . . . . . . . . . . . . . . . . 157
8.5.5
Inicialización predeterminada de componentes. . . . . . . . . . . . . . . . . 158
8.6
Accesibilidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
8.6.1
Los atributos públicos y privados . . . . . . . . . . . . . . . . . . . 159
8.6.2
Más control del acceso desde el módulo. . . . . . . . . . . . . . . . 161
8.7
Funciones de puntero que denotan variables . . . . . . . . . . . . . . . . . . . . . . 161
8.8
El puntero, el destino y las declaraciones asignables . . . . . . . . . . . . . . . . . 163
8,9
La intención y las declaraciones opcionales. . . . . . . . . . . . . . . . . . . . . . . 163
8.10 El atributo de ahorro. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
8.11 Volatilidad. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
8.11.1 El atributo volátil. . . . . . . . . . . . . . . . . . . . . A. Aaaaaaaaaaaaaaaaaanaaaaaaaaaaa!.?! Aaa!.?!!!?!!
Aaaaaah!.?.?!?..?!..?..!..?.....?..... Y.... !.C.Y .Anmasi., Ai..!.... .AAAAAAAAAAJAAAAAHAAAHYYYYYH. AYUDA.
Aaaaaaalaaalaaaaaaaaaaaaah! 'S.?...! A.?.!.?.!.?.!..?..?.. Y...... .O...... &... .SineBargo.com . . . 165
8.11.2 Cobertura volátil. . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
8.11.3 Argumentos volátiles. . . . . . . . . . . . . . . . . . . . . . . . . . . 167
8.12 El atributo asíncrono. . . . . . . . . . . . . . . . . . . . . . . . . . . 168
8.13 La construcción de bloques. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
8.14 Su declaración. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
8.15 Definiciones de tipo derivado. . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
8.16 La declaración de declaración de tipo. . . . . . . . . . . . . . . . . . . . . . . . . 176
8.17 Especificación de parámetros de tipo y tipo. . . . . . . . . . . . . . . . . . . . . 177
8.18 Expresiones de especificación. . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
8.19 Constructores de estructuras. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
8.20 La declaración de la lista de nombres. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
8.21 Resumen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

Página 14
Contenidos xiii
9 procedimientos y módulos intrínsecos
187
9.1
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
9.1.1
Llamadas de palabras clave. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
9.1.2
Categorías de procedimientos intrínsecos . . . . . . . . . . . . . . . . . . . 188
9.1.3
La declaración intrínseca . . . . . . . . . . . . . . . . . . . . . . . . 188
9.1.4
Argumentintents. . . . . . . . . . . . . . . . . . . . . . . . . . . 188
9.2
Consultafuncionesforanytipo. . . . . . . . . . . . . . . . . . . . . . . . . 188
9.3
Funciones numéricas elementales. . . . . . . . . . . . . . . . . . . . . . . . . . 189
9.3.1
Funciones elementales que pueden convertir. . . . . . . . . . . . . . . . . 189
9.3.2
Funciones elementales que no se convierten. . . . . . . . . . . . . . . . 191
9.4
Funciones matemáticas elementales. . . . . . . . . . . . . . . . . . . . . . . 191
9.5
Funciones transformacionales para las funciones de Bessel. . . . . . . . . . . . . . . . 194
9.6
Carácter elemental y funciones lógicas . . . . . . . . . . . . . . . . . . . 194
9.6.1
Conversiones de caracteres enteros . . . . . . . . . . . . . . . . . . . . 194
9.6.2
Funciones de comparación léxica. . . . . . . . . . . . . . . . . . . . . 195
9.6.3
Funciones elementales de manejo de cadenas . . . . . . . . . . . . . . . . . 195
9.6.4
Conversión lógica. . . . . . . . . . . . . . . . . . . . . . . . . . 196
9,7
Funciones de manejo de cadenas no elementales . . . . . . . . . . . . . . . . . . . 196
9.7.1
Función de consulta de manejo de cadenas. . . . . . . . . . . . . . . . . . . 196
9.7.2
Funciones transformacionales de manejo de cadenas . . . . . . . . . . . . . . 196
9,8
Función de consulta de caracteres. . . . . . . . . . . . . . . . . . . . . . . . . . . 197
9,9
Funciones de consulta numérica y manipulación. . . . . . . . . . . . . . . . . 197
9.9.1
Modelos para datos enteros y reales . . . . . . . . . . . . . . . . . . . . 197
9.9.2
Funciones de consulta numérica . . . . . . . . . . . . . . . . . . . . . . 198
9.9.3
Funciones elementales para manipular reales . . . . . . . . . . . . . . . 199
9.9.4
Funciones transformacionales para valores amables . . . . . . . . . . . . . . 199
9.10 Procedimientos de manipulación de bits. . . . . . . . . . . . . . . . . . . . . . . . . . 200
9.10.1 Modelforbitdata. . . . . . . . . . . . . . . . . . . . . . . . . . . 200
9.10.2 Función de consulta. . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
9.10.3 Funciones básicas del elemento básico. . . . . . . . . . . . . . . . . . . . . . . 201
9.10.4 Operaciones de cambio. . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
9.10.5 Subrutina elemental. . . . . . . . . . . . . . . . . . . . . . . . . 202
9.10.6 Comparación a nivel de bit (sin signo). . . . . . . . . . . . . . . . . . . . 203
9.10.7 Cambio de doble ancho. . . . . . . . . . . . . . . . . . . . . . . . . 203
9.10.8 Reducciones bit a bit. . . . . . . . . . . . . . . . . . . . . . . . . . . 204 204
9.10.9 Bits de conteo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 204
9.10.10 Producir máscaras de bits. . . . . . . . . . . . . . . . . . . . . . . . . . 204 204
9.10.11 Fusionar bits. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 204
9.11 Función de transferencia. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
9.12 Funciones de multiplicación de vectores y matrices. . . . . . . . . . . . . . . . . . 205
9.13 Funciones transformacionales que reducen matrices. . . . . . . . . . . . . . . . . 206
9.13.1 Caso de argumento único. . . . . . . . . . . . . . . . . . . . . . . . . 206
9.13.2 Additionalargumentdim. . . . . . . . . . . . . . . . . . . . . . . 207
9.13.3 Máscara de argumento opcional. . . . . . . . . . . . . . . . . . . . . . . 207
9.14 Funciones de consulta de matriz. . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

Página 15
xiv Contenido
9.14.1 Contigüidad. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
9.14.2 Límites, forma y tamaño. . . . . . . . . . . . . . . . . . . . . . . . 208
9.15 Funciones de construcción y manipulación de matrices. . . . . . . . . . . . . . . . 209
9.15.1 La función elemental militar. . . . . . . . . . . . . . . . . . . . . 209
9.15.2 Arreglos de embalaje y desembalaje. . . . . . . . . . . . . . . . . . . . . 209
9.15.3 Rehapinganarray. . . . . . . . . . . . . . . . . . . . . . . . . . 210
9.15.4 Función transformacional para la replicación. . . . . . . . . . . . . . . 210
9.15.5 Funciones de cambio de matriz. . . . . . . . . . . . . . . . . . . . . . . . 210
9.15.6 Matrixtranspose. . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
9.16 Funciones transformacionales para la ubicación geométrica. . . . . . . . . . . . . . 211
9.17 Función transformacional para disociados o no asignados . . . . . . . . . . 212
9.18 Subrutinas intrínsecas no elementales. . . . . . . . . . . . . . . . . . . . . . 212
9.18.1 Reloj en tiempo real. . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
9.18.2 Tiempo de CPU. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
9.18.3 Números aleatorios. . . . . . . . . . . . . . . . . . . . . . . . . . . 214
9.18.4 Ejecutar otro programa. . . . . . . . . . . . . . . . . . . . . . 214
9.19 Acceso al entorno informático. . . . . . . . . . . . . . . . . . . . . 215
9.19.1 Variables del entorno. . . . . . . . . . . . . . . . . . . . . . . . . 215
9.19.2 Información sobre la invocación del programa. . . . . . . . . . . . . . 216
9.20 Funciones elementales para pruebas I / Ostatus. . . . . . . . . . . . . . . . . . . 217
9.21 Sizeofanobjectinmemory. . . . . . . . . . . . . . . . . . . . . . . . . . 217
9.22 Procedimientos diversos. . . . . . . . . . . . . . . . . . . . . . . . . . . 218
9.23 Módulos intrínsecos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
9.24 Fortranenvironment. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
9.24.1 Constantes nombrados. . . . . . . . . . . . . . . . . . . . . . . . . . . 219
9.24.2 Información de compilación. . . . . . . . . . . . . . . . . . . . . . . 220
9.24.3 Nombres para tipos comunes. . . . . . . . . . . . . . . . . . . . . . . 220
9.24.4 Kindarrays. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
9.24.5 Tipo de bloqueo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
9.25 Resumen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
10 Transferencia de datos
225
10.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
10.2 Conversión de números. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
10.3 I / Olists. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
10.4 Definición de formato. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
10.5 Números de unidad. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
10.6 Archivos internos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
10.7 Entrada formateada. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
10.8 Salida formateada. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
10.9 Lista dirigida I / O. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
10.10 Lista de nombres I / O. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
10.11 E / S sin avance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
10.12 I / O sin formato. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
10.13 Archivos de acceso directo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241

Página 16
Contenido xv
10.14 UTF-8files. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
10.15 Entrada / salida asíncrona. . . . . . . . . . . . . . . . . . . . . . . . . . 243
10.15.1 Ejecución asincrónica. . . . . . . . . . . . . . . . . . . . . . . 243
10.15.2 El atributo asincrónico. . . . . . . . . . . . . . . . . . . . . . 245
10.16 Streamaccessfiles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
10.17 Ejecución de una declaración de transferencia de datos. . . . . . . . . . . . . . . . . . . . . 247
10.18 Resumen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
11 Editar descriptores
249
11.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
11.2 Descriptor de caracteres con caracteres. . . . . . . . . . . . . . . . . . . . . . . . 249
11.3 Descriptores de datos editados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
11.3.1 Repetir recuentos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
11.3.2 Formateo de enteros. . . . . . . . . . . . . . . . . . . . . . . . . . . 251
11.3.3 Realformateo. . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
11.3.4 Formateo complejo. . . . . . . . . . . . . . . . . . . . . . . . . . 253
11.3.5 Formato lógico. . . . . . . . . . . . . . . . . . . . . . . . . . . 253
11.3.6 Formateo de caracteres. . . . . . . . . . . . . . . . . . . . . . . . . 253
11.3.7 Formato general. . . . . . . . . . . . . . . . . . . . . . . . . . 254
11.3.8 Formato derivado. . . . . . . . . . . . . . . . . . . . . . . . 255
11.4 Descriptores controlados. . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
11.4.1 Factor de escala. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
11.4.2 Tabulación y espaciado. . . . . . . . . . . . . . . . . . . . . . . . 256
11.4.3 Nuevos registros (recortes). . . . . . . . . . . . . . . . . . . . . . 257
11.4.4 Colonediting. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
11.5 Modos de conexión de archivos modificables. . . . . . . . . . . . . . . . . . . . . . . 258
11.5.1 Interpretación en blanco embebido. . . . . . . . . . . . . . . . . . . . 258
11.5.2 Modo de entrada / salida. . . . . . . . . . . . . . . . . . . . . . 259
11.5.3 Valores positivos de Signson. . . . . . . . . . . . . . . . . . . . . . . . 259
11.5.4 Comando decimal para entrada / salida. . . . . . . . . . . . . . . . . . . 260
11.6 Entrada / salida de tipo derivado definida. . . . . . . . . . . . . . . . . . . . . . . 260
11.7 Entrada / salida recursiva. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
11.8 Resumen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
12 Operaciones en archivos externos
267
12.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
12.2 Declaraciones de posicionamiento para archivos secuenciales. . . . . . . . . . . . . . . . . . . 268
12.2.1 Thebackspacestatement. . . . . . . . . . . . . . . . . . . . . . . 268
12.2.2 Declaración de viento. . . . . . . . . . . . . . . . . . . . . . . . . 268
12.2.3 Declaración del archivo final. . . . . . . . . . . . . . . . . . . . . . . . . 269
12.2.4 Declaraciones de transferencia de datos. . . . . . . . . . . . . . . . . . . . . . . . 269
12.3 La declaración al ras. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
12.4 Theopenstatement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
12.5 Theclosestatement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
12.6 La declaración requerida. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274

Página 17
xvi Contenido
12.7 Resumen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
13 características de parámetros de tipo avanzado
279
13.1 Consulta de parámetros de tipo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
13.2 Tipos derivados parametrizados. . . . . . . . . . . . . . . . . . . . . . . . . . 279
13.2.1 Definición de un tipo derivado parametrizado. . . . . . . . . . . . . . . . 280
13.2.2 Parámetros de tipos supuestos y diferidos. . . . . . . . . . . . . . . . 281
13.2.3 Valores de parámetro de tipo predeterminado. . . . . . . . . . . . . . . . . . . . . 281
13.2.4 Consulta de parámetros de tipo derivado. . . . . . . . . . . . . . . . . . . . 282
13.2.5 Constructor de estructuras. . . . . . . . . . . . . . . . . . . . . . . . . 282
14 punteros de procedimiento
285
14.1 Interfaces abstractas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
14 .2 Punteros de procedimiento. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
14.2.1 Punteros de procedimientos nombrados. . . . . . . . . . . . . . . . . . . . . . 287
14.2.2 Procedimientocomponentes de puntero. . . . . . . . . . . . . . . . . . . . 287
14.2.3 El atributo passpass. . . . . . . . . . . . . . . . . . . . . . . . . . . 288
14.2.4 Procedimientos internos como objetivos de un puntero de procedimiento . . . . . . . . . 289
15 Programación orientada a objetos
291
15.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
15.2 Extensión de tipo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
15.2.1 Tipo de extensión y tipo de parámetros. . . . . . . . . . . . . . . . . 293
15.3 Polimorficentidades. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
15.3.1 Introducción topolimorficentidades. . . . . . . . . . . . . . . . . 293
15.3.2 Establecimiento del tipo dinámico. . . . . . . . . . . . . . . . . . . . 294
15.3.3 Limitaciones en el uso de una variable polimórfica. . . . . . . . . . . 295
15.3.4 Polymorphicarraysandscalars. . . . . . . . . . . . . . . . . . . . 295
15.3.5 Polimorficentidades ilimitadas. . . . . . . . . . . . . . . . . . . . 295
15.3.6 Polimorficentidades y resolución genérica. . . . . . . . . . . . . 296
15.4 Tipo y fuente de asignación. . . . . . . . . . . . . . . . . . . . . . . . . 297
15.4.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
15.4.2 Asignación tipificada y parámetros de tipo diferido. . . . . . . . . . . . 297
15.4.3 Variables polimórficas y ubicación de tipos. . . . . . . . . . . . . 298
15.4.4 Asignación de fuente. . . . . . . . . . . . . . . . . . . . . . . . . . . 298
15.5 Asignación para variables polimórficas localizables. . . . . . . . . . . . . . 300
15.6 La construcción asociada. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300
15.7. Estos tipos de construcción. . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
15.8 Procedimientos vinculados por tipo. . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
15.8.1 Procedimientos vinculados a tipos específicos. . . . . . . . . . . . . . . . . . . . 305
15.8.2 Procedimientos vinculados al tipo genérico. . . . . . . . . . . . . . . . . . . . 306
15.8.3 Extensión de tipo y procedimientos de tipo encuadernado. . . . . . . . . . . . . . 308
15.9 Diseño para sobrescribir. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
15.10 Enlaces diferidos y tipos abstractos . . . . . . . . . . . . . . . . . . . . . 312
15.11 Finalización. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313

Página 18
Contenidos xvii
15.11.1 Extensión de tipo y subrutinas finales. . . . . . . . . . . . . . . . . 315
15.12 Ejemplo de procedimiento de encapsulación verde. . . . . . . . . . . . . . . . . . . . . . . 315
15.13 Funciones de consulta de tipo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
16 submódulos
321
16.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
16.2 Procedimientos de módulos separados. . . . . . . . . . . . . . . . . . . . . . . . . . 321
16 .3 Submódulos de submódulos. . . . . . . . . . . . . . . . . . . . . . . . . . 323
16.4 Submoduleentities. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
16.5 Submódulos y uso de asociación. . . . . . . . . . . . . . . . . . . . . . . . 323
16.6 Las ventajas de los submódulos. . . . . . . . . . . . . . . . . . . . . . . . . 324
17 Coarrays
325
17.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
17.2 Imágenes de referencia. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
17.3 Las propiedades de los arrays. . . . . . . . . . . . . . . . . . . . . . . . . . . 327
17.4 Acceso a matrices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
17.5 La declaración de sincronización. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
17.6 Matrices asignables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
17.7 Las matrices con componentes localizables o de puntero. . . . . . . . . . . . . . . 331
17.7.1 Componentes de datos. . . . . . . . . . . . . . . . . . . . . . . . . . . 332
17.7.2 Componentes del puntero del procedimiento. . . . . . . . . . . . . . . . . . . . 333
17.8 Componentes de la matriz. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
17.9 Procedimientos de arrays. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
17.10 Referencias a subobjetos polimórficos. . . . . . . . . . . . . . . . . . . . . 335
17.11 Atributos volátiles y asincrónicos. . . . . . . . . . . . . . . . . . . . . . 336
17.12 Interoperabilidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
17.13 Sincronización. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
17.13.1 Segmentos de ejecución. . . . . . . . . . . . . . . . . . . . . . . . . . 336
17.13.2 La declaración de imágenes sincronizadas. . . . . . . . . . . . . . . . . . . . . . 337
17.13.3 Las declaraciones de bloqueo y desbloqueo. . . . . . . . . . . . . . . . . . . . 338
17.13.4 Secciones críticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
17.13.5 Subrutinas atómicas y la declaración de memoria de sincronización . . . . . . . . . 341
17.13.6 Los especificadores stat = y errmsg = en las declaraciones de sincronización . . . 341
17 .13.7 Las declaraciones de control de imagen. . . . . . . . . . . . . . . . . . . . . 342
17.14 Terminación del programa. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
17.15 Entrada / salida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
17.16 Procedimientos intrínsecos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
17.16.1 Funciones de consulta. . . . . . . . . . . . . . . . . . . . . . . . . . . 344
17.16.2 Funciones transformacionales. . . . . . . . . . . . . . . . . . . . . . 345
17.17 Matrices de diferentes tamaños en diferentes imágenes . . . . . . . . . . . . . . . . . 345
18 Manejo de excepciones de punto flotante
347
18.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
18.2 El estándar IEEE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347

Página 19
xviii Contenido
18.3 Acceso a las características. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
18.4 Las banderas de Fortran. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
18.5 Detención. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
18.6 El modo circundante. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
18.7 Theunderflowmode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
18.8 Themoduleieee_exceptions. . . . . . . . . . . . . . . . . . . . . . . . . . 353
18.8.1 Tipos derivados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
18.8.2 Consulta sobre las excepciones EEEE. . . . . . . . . . . . . . . . . . . 354
18.8.3 Subrutinas para las banderas y modos de detención . . . . . . . . . . . . . 354
18.8.4 Subrutinas para todo el estado de coma flotante . . . . . . . . 355
18.9 Themoduleieee_arithmetic. . . . . . . . . . . . . . . . . . . . . . . . . . 356
18.9.1 Tipos derivados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
18.9.2 Consulta sobre IEEE aritmética. . . . . . . . . . . . . . . . . . . 356
18.9.3 Funciones elementales. . . . . . . . . . . . . . . . . . . . . . . . . . 358
18.9.4 Subrutinas no elementales. . . . . . . . . . . . . . . . . . . . . . 360
18.9.5 Función transformacional para el valor de la humanidad. . . . . . . . . . . . . . . 361
18.10 Ejemplos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
18.10.1 Producto de punto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
18.10.2 Llamar a procedimientos alternativos. . . . . . . . . . . . . . . . . . . . . 362
18.10.3 Llamar a un código alternativo en línea . . . . . . . . . . . . . . . . . . . . 363
18.10.4 Función de hipotenusa confiable. . . . . . . . . . . . . . . . . . . . . 363
18.10.5 Acceso a valores aritméticos IEEE. . . . . . . . . . . . . . . . . . . 365
19 Interoperabilidad con C
367
19.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
19.2 Interoperabilidad de los tipos intrínsecos. . . . . . . . . . . . . . . . . . . . . . . 367
19.3 Interoperabilidad con tipos de componentes. . . . . . . . . . . . . . . . . . . . . 368
19.4 Interoperabilidad de los tipos derivados. . . . . . . . . . . . . . . . . . . . . . . . 370
19.5 Forma y longitud de caracteres y acuerdo. . . . . . . . . . . . . . . . . . . 371
19.6 Interoperabilidad de variables. . . . . . . . . . . . . . . . . . . . . . . . . . 373
19.7 Functionc_sizeof. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
19.8 El atributo de valor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
19.9 Interoperabilidad de los procedimientos. . . . . . . . . . . . . . . . . . . . . . . . . 375
19.10 Interoperabilidad de datos globales . . . . . . . . . . . . . . . . . . . . . . . . . 377
19.11 Invocación de una función de Fortran. . . . . . . . . . . . . . . . . . . . . . 377
19.12 Invocación de Fortrandesde C. . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
19.13 Enumeraciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381
20 mejoras de coarray Fortran 2018
383
20.1 Equipos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383
20.2 Fallo de imagen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
20.3 Formulación de declaración. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
20.4 Construcción del equipo de cambio. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
20.5. . . . . . . . . . . . . . . . . . . . . . . . . . 386
20.6 Falla crítica de construcción e imagen. . . . . . . . . . . . . . . . . . . . . . 386

Página 20
Contenidos xix
20.7 Bloqueo y desbloqueo de declaraciones y fallas de imagen. . . . . . . . . . . . . . . . 386
20.8 Syncteamstatement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
20.9 Selectores de imagen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
20.10 Llamadas de procedimiento y equipos. . . . . . . . . . . . . . . . . . . . . . . . . . . 388
20.11 Funciones intrínsecas get_team y team_number. . . . . . . . . . . . . . . . 388
20.12 Función intrínseca índice_imagen. . . . . . . . . . . . . . . . . . . . . . . . . 388
20.13 Función intrínseca num_images. . . . . . . . . . . . . . . . . . . . . . . . . 389
20.14 Función intrínseca this_image. . . . . . . . . . . . . . . . . . . . . . . . . . 390
20.15 Función intrínseca de forma. . . . . . . . . . . . . . . . . . . . . . . . . . . 390
20.16 Intrinsicfunctionmove_alloc. . . . . . . . . . . . . . . . . . . . . . . . . 390
20.17 Declaración de falla de imagen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
20.18 Detección de imágenes fallidas y detenidas. . . . . . . . . . . . . . . . . . . . . . 391
20.19 Subrutinas colectivas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
20.20 Subrutinas Newatomics. . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
20.21 Imágenes fallidas y stat = especificadores . . . . . . . . . . . . . . . . . . . . . . . 395
20.22 Eventos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
21 mejoras de Fortran 2018 a la interoperabilidad con C
397
21.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
21.2 Argumentos opcionales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
21.3 Interoperabilidad de bajo nivel. . . . . . . . . . . . . . . . . . . . . . . . . . 399
21.4 Longitud de caracteres asumida. . . . . . . . . . . . . . . . . . . . . . . . . . . 400
21.5 Cdescriptores. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
21.5.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
21.5.2 Miembros estándar. . . . . . . . . . . . . . . . . . . . . . . . . . . 401
21.5.3 Clasificación de argumentos (códigos de atributo). . . . . . . . . . . . . . . 402
21.5.4 Tipo de datos de argumento. . . . . . . . . . . . . . . . . . . . . . . . . . 402
21.5.5 Información de disposición de matriz. . . . . . . . . . . . . . . . . . . . . . . 403
21.6 Acceso a objetos fortrano. . . . . . . . . . . . . . . . . . . . . . . . . . . 404
21.6.1 Atravesar arrays contiguos contiguos. . . . . . . . . . . . . . . . . 404
21.6.2 La programación genérica es de tipo supuesta. . . . . . . . . . . . . . 405
21.6.3 Atravesar diagramas contiguos no contiguos. . . . . . . . . . . . . . . 405
21.6.4 Fortranpointeroperations. . . . . . . . . . . . . . . . . . . . . . . 407
21.6.5 Objetos asignables. . . . . . . . . . . . . . . . . . . . . . . . . . 409
21.6.6 Manipulación de matrices de cualquier broma. . . . . . . . . . . . . . . . . . . . . . 410
21.6.7 Acceso a elementos de matriz individuales a través de un descriptor C . . . . . . . 411
21.6.8 Manejo de errores de funciones CFI. . . . . . . . . . . . . . . . . . 414
21.7 CallingFortranwithCdescriptors. . . . . . . . . . . . . . . . . . . . . . . 414
21.7.1 Asignación de almacenamiento para un descriptor. . . . . . . . . . . . . . . . . 414
21.7.2 Establecimiento de un descriptor. . . . . . . . . . . . . . . . . . . . . . 415
21.7.3 Construcción de una sección de matriz. . . . . . . . . . . . . . . . . . . . . 416
21.7.4 Acceso a componentes. . . . . . . . . . . . . . . . . . . . . . . . 419
21.8 Restricciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
21.8.1 Otras limitaciones en los descriptores. . . . . . . . . . . . . . . . . . 420
21.8.2 Duración de los descriptores. . . . . . . . . . . . . . . . . . . . . . . 420

Página 21
xx Contenidos
21.9 Varios cambios de interoperabilidad. . . . . . . . . . . . . . . . . . . 420
21.9.1 Interoperabilidad con el Ctypeptrdiff_t . . . . . . . . . . . . . . . 420
21.9.2 Relajación de los requisitos de interoperabilidad. . . . . . . . . . . . . 420
22 Fortran 2018 conformidad con ISO / IEC / IEEE 60559: 2011
423
22.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423
22.2 Valores subnormales. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423
22.3 Tipo para modos de punto flotante. . . . . . . . . . . . . . . . . . . . . . . . . 423
22.4 Modos de redondeo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424
22.5 Conversiones redondeadas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424
22.6 Fusionmultiply-add. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
22.7 Signo de prueba. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
22.8 Conversión a tipo de entidad. . . . . . . . . . . . . . . . . . . . . . . . . . . 425
22.9 Función restante. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
22.10 Valores máximos y mínimos. . . . . . . . . . . . . . . . . . . . . . . . 425
22.11 Números de máquina adyacentes. . . . . . . . . . . . . . . . . . . . . . . . . . 426
22.12 Comparaciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
22.13 Hexadecimal significand input / output. . . . . . . . . . . . . . . . . . . . . 427
23 características menores de Fortran 2018
429
23.1 Accesibilidad predeterminada para entidades a las que se accede desde un módulo . . . . . . . . . . . 429
23.2 Exigir declaraciones explícitas de procedimientos. . . . . . . . . . . . . . . . . . . 429
23.3 Usar las propiedades de un objeto en su inicialización . . . . . . . . . . . . . . 430
23.4 Procedimientos genéricos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
23.4.1 Más especificación genérica concisa. . . . . . . . . . . . . . . . . . 430
23.4.2 Reglas para la ambigüedad. . . . . . . . . . . . . . . . . . . . . . . 431
23.5 Mejoras en el despliegue de los obstáculos. . . . . . . . . . . . . . . . . . . . . . 431
23.6 Nuevos procedimientos intrínsecos. . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
23.6.1 Comprobación de conversiones seguras. . . . . . . . . . . . . . . . . . . 431
23.6.2 Generalizedarrayreduction. . . . . . . . . . . . . . . . . . . . . . 432
23.6.3 Control del generador de números aleatorios. . . . . . . . . . . . . . 432
23.7 Procedimientos intrínsecos existentes. . . . . . . . . . . . . . . . . . . . . . . . . . 433
23.7.1 Señal de funciones intrínsecas. . . . . . . . . . . . . . . . . . . . . . . . . 433
23.7.2 Funciones intrínsecas extend_type_of y same_type_as . . . . . . . . 433
23.7.3 Simplificación de llamadas de la función intrínseca cmplx. . . . . . . . 433
23.7.4 Eliminar muchas restricciones de argumento. . . . . . . . . . . . . . . 434
23.7.5 Tipos de argumentos de procedimientos intrínsecos e IEEE. . . . . . . . 434
23.7.6 Subrutinas intrínsecas que acceden al entorno informático . . . . . 435
23.8 Uso de características no estándar. . . . . . . . . . . . . . . . . . . . . . . . . . 435
23.9 Tipo de la variable variable integrada en doloops. . . . . . . . . . . . . . . . . . 435
23.10 Mejora el rendimiento concurrente. . . . . . . . . . . . . . . . . . . . . 436
23.11 Control de la asociación de anfitriones . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
23.12 Intención en los requisitos y el atributo de valor . . . . . . . . . . . . . . . . . 438
23.13 Procedimientos puros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438
23.14 Procedimientos recursivos y no recursivos. . . . . . . . . . . . . . . . . . . . 438

Página 22
Contenidos xxi
23.15 Entrada / salida. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439
23.15.1 Edición de ancho de campo más mínima. . . . . . . . . . . . . . . . . . . 439
23.15.2 Recuperación de errores de formato de entrada . . . . . . . . . . . . . . . . . 439
23.15.3 Avance de entrada con tamaño =. . . . . . . . . . . . . . . . . . . . . . 439
23.15.4 Precisión de stat = variables . . . . . . . . . . . . . . . . . . . . . . 439
23.15.5 Conecte un archivo a más de una unidad . . . . . . . . . . . . . . . . . 439
23.15.6 Mejoras para investigar. . . . . . . . . . . . . . . . . . . . . . . 440
23.15.7 Comunicación asincrónica. . . . . . . . . . . . . . . . . . . . 440
23.16 Rango asumido. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
23.16.1 Objetos de rango asumido. . . . . . . . . . . . . . . . . . . . . . . . . 440
23.16.2 Theselectrankconstruct. . . . . . . . . . . . . . . . . . . . . . . 442
A Características obsoletas
445
A.1 Introducción. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
A.2 Asociación de almacenamiento. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
A.3 Forma alternativa de operador relacional. . . . . . . . . . . . . . . . . . . . . 446
A.4 La inclusión. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
A.5 La declaración do while. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
A.6 Doble precisión real. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448
A.7 Las declaraciones de dimensión, codimensión y parámetro. . . . . . . . . . . 448
A.8 Mapeo no predeterminado para tipeo implícito. . . . . . . . . . . . . . . . . . . 449
A.9 Características obsoletas de Fortran 2008. . . . . . . . . . . . . . . . . . . . . . . 450
A.9.1 La declaración de memoria de sincronización, y atomic_define y atomic_ref . . . 450
A.9.2 Componentes de tipo c_ptr o c_funptr. . . . . . . . . . . . . . . . 453
A.9.3 Declaraciones de tipo. . . . . . . . . . . . . . . . . . . . . . . . . . . 453
A.9.4 Denotando argumentos secundarios. . . . . . . . . . . . . . . . . . . . . . 454
A.9.5 Forma alternativa de constante compleja. . . . . . . . . . . . . . . . 455
B Funciones obsoletas y eliminadas
457
B.1 Características obsoletas en Fortran 95. . . . . . . . . . . . . . . . . . . . . . . 457
B.1.1 Fixedsourceform. . . . . . . . . . . . . . . . . . . . . . . . . . . 457
B.1.2 Computedgoto. . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
B.1.3 Especificación de longitud de caracteres con carácter * . . . . . . . . . . . . 458
B.1.4 Declaraciones de datos entre ejecutables. . . . . . . . . . . . . . . . . . 458
B.1.5 Funciones de declaración. . . . . . . . . . . . . . . . . . . . . . . . . . 459
B.1.6 Longitud de caracteres asumida de los resultados de la función. . . . . . . . . . . . . 460
B.1.7 Retorno alternativo. . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
B.2 Característica obsoleta en Fortran 2008: Declaración de entrada. . . . . . . . . . . . . 462
B.3 Características obsoletas en Fortran 2018. . . . . . . . . . . . . . . . . . . . . 463
B.3.1 La declaración general y la construcción. . . . . . . . . . . . . . . . . . 463
B.3.2 La declaración de equivalencia. . . . . . . . . . . . . . . . . . . . . . 466
B.3.3 El bloque común. . . . . . . . . . . . . . . . . . . . . . . . . . 468
B.3.4 La unidad del programa de datos de bloque. . . . . . . . . . . . . . . . . . . . . 470
B.3.5 La construcción marcada. . . . . . . . . . . . . . . . . . . . . . . 471
B.3.6 Nombres específicos de procedimientos intrínsecos. . . . . . . . . . . . . . . . 472

Página 23
xxii Contenido
B.4 Características eliminadas en Fortran95. . . . . . . . . . . . . . . . . . . . . . . . . 474
B.5 Característica eliminada en Fortran 2003: Control de carro. . . . . . . . . . . . . . . 475
B.6 Características eliminadas en Fortran 2018. . . . . . . . . . . . . . . . . . . . . . . . 475
C Ejemplo de lista orientada a objetos
477
D Soluciones a ejercicios
485
Índice
507

Página 24

1. ¿De dónde viene Fortran?


1.1 Introducción
Este libro trata sobre los lenguajes de programación Fortran 2008 y Fortran 2018,
establecer una descripción razonablemente concisa de todo el lenguaje. La forma elegida por su
La presentación es la de un libro de texto destinado a la enseñanza o el aprendizaje del idioma.
Después de este capítulo introductorio, los capítulos se escriben para que los programas simples puedan ser
codificado después de los primeros tres (en elementos del lenguaje, expresiones y tareas, y control)
han sido leídos Los programas sucesivamente más complejos se pueden escribir como la información
en cada capítulo posterior se absorbe. El Capítulo 5 describe el concepto importante de
módulo y los muchos aspectos de los procedimientos. Los capítulos 6 y 7 completan la descripción de
Las potentes funciones de matriz, el Capítulo 8 considera los detalles de la especificación de objetos de datos
tipos derivados, y el Capítulo 9 detalla los procedimientos intrínsecos. Capítulos 10, 11 y 12 cubren
todas las características de entrada / salida de manera tal que el lector también pueda abordar esto más
área difícil característica por característica, pero siempre con un subconjunto útil ya cubierto. Muchos pero
no todas las características descritas en los capítulos 2 a 12 estaban disponibles en Fortran 95.
El Capítulo 13 trata con los tipos de datos parametrizados, el Capítulo 14 con punteros de procedimiento,
Capítulo 15 con programación orientada a objetos, y Capítulo 16 con submódulos. Coarrays
que son importantes para el procesamiento en paralelo, se describen en el Capítulo 17. El Capítulo 18 describe
manejo de excepciones de punto flotante, y el Capítulo 19 trata de la interoperabilidad con el C
lenguaje de programación. Ninguna de las características de los capítulos 13 a 19 estaba disponible antes
a Fortran 2003 o, en los casos de submódulos y matrices, Fortran 2008. Finalmente, el
Los capítulos restantes, 20 a 23, describen las diversas mejoras aportadas al lenguaje por
El último estándar, Fortran 2018.
En los Apéndices A y B describimos características que son redundantes en el lenguaje. Esos de
El Apéndice A todavía es parte del estándar, pero nosotros usamos su uso en desuso, mientras que
del Apéndice B están designados como obsoletos o eliminados por el estándar mismo.
Este capítulo introductorio tiene la tarea de preparar la escena para los que siguen. Sección 1.2
presenta la historia temprana de Fortran, comenzando con su introducción hace más de sesenta años.
La sección 1.3 continúa con el desarrollo del estándar Fortran 90, resume su
nuevas características importantes y describe cómo se desarrollan los estándares; La sección 1.4 analiza el
mecanismo que se ha adoptado para permitir que el lenguaje evolucione. Secciones 1.5 a 1.11
considere el desarrollo de Fortran 95 y sus extensiones, luego de Fortran 2003, Fortran 2008,
y Fortran 2018. La sección final considera los requisitos sobre programas y procesadores.
para conformidad con el estándar.
Fortran moderno explicado, 2da edición. Michael Metcalf, John Reid y Malcolm Cohen. prensa de la Universidad de Oxford
(2018) cG Michael Metcalf, John Reid y Malcolm Cohen 2018. DOI 10.1093 / oso / 9780198811893.001.0001

Página 25
2 Fortran moderno explicado
1.2 Historia temprana de Fortran
La programación en los primeros días de la informática fue tediosa en extremo. Programadores
requiere un conocimiento detallado de las instrucciones, registros y otros aspectos de la central
unidad de procesamiento (CPU) de la computadora para la cual estaban escribiendo código. La fuente
El código en sí fue escrito en una notación numérica. En el curso del tiempo códigos mnemotécnicos
se introdujeron, una forma de codificación conocida como máquina o código de ensamblaje. Estos códigos
fueron traducidos a las palabras de instrucción por programas conocidos como ensambladores. En la década de 1950
se hizo cada vez más evidente que esta forma de programación era muy inconveniente,
aunque sí permitió que la CPU se usara de manera muy eficiente.
Estas dificultades impulsaron a un equipo dirigido por John Backus de IBM a desarrollar uno de los primeros
idiomas de alto nivel, Fortran. Su objetivo era producir un lenguaje que fuera simple de
entender pero casi tan eficiente en ejecución como lenguaje ensamblador. En esto tuvieron éxito
más allá de sus sueños más salvajes. El idioma era realmente simple de aprender, ya que era posible
escribe fórmulas matemáticas casi como generalmente se escriben en textos matemáticos. (Los
El nombre Fortran es una contracción de 'traducción de fórmulas'.) Esto permitió que los programas de trabajo
escrito más rápido que antes, por solo una pequeña pérdida de eficiencia, como un gran cuidado
se dedicó a la generación de código objeto rápido.
Pero Fortran fue revolucionario e innovador. Los programadores fueron relevados de
la tediosa carga de usar lenguaje ensamblador, y las computadoras se hicieron accesibles para cualquier
científico o ingeniero dispuesto a dedicar un poco de esfuerzo a adquirir un conocimiento práctico de
Fortran Ya no era necesario ser un experto en computadoras para poder escribir
programas de aplicación.
Fortran se extendió rápidamente al satisfacer una necesidad real. Inevitablemente, dialectos de la lengua.
desarrollado, lo que condujo a problemas en el intercambio de programas entre computadoras, y así
en 1966, la entonces Asociación Estadounidense de Normas (más tarde las Normas Nacionales Estadounidenses
Institute, ANSI) presentó el primer estándar para un lenguaje de programación, ahora conocido
como Fortran 66.
Pero la proliferación de dialectos siguió siendo un problema después de la publicación de 1966.
estándar. Hubo una implementación generalizada de características que eran esenciales para grandes
programas de escala, pero que fueron ignorados por el estándar. Diferentes compiladores implementados
tales características de diferentes maneras. Estas dificultades fueron parcialmente resueltas por la publicación.
de un nuevo estándar en 1978, conocido como Fortran 77, que incluía varias características nuevas que
se basaron en extensiones de proveedores o preprocesadores.
1.3 La unidad para el estándar Fortran 90
Después de treinta años de existencia, Fortran estaba lejos de ser el único lenguaje de programación.
disponible en la mayoría de las computadoras, pero la superioridad de Fortran siempre había estado en el área de
aplicaciones numéricas, científicas, de ingeniería y técnicas y así, para que sea
actualizado adecuadamente, el comité técnico acreditado por ANSI X3J3 (posteriormente
conocido como J3 y ahora formalmente como PL22.3), trabajando como un organismo de desarrollo para la ISO
comité ISO / IEC JTC1 / SC22 / WG5, una vez más preparó un nuevo estándar, ahora conocido como
Fortran 90. Utilizaremos las abreviaturas J3 y WG5 para estos dos comités.
¿De dónde viene Fortran? 3
J3 está compuesto por representantes de proveedores de hardware y software de computadoras, usuarios y
academia Ahora está acreditado por el NCITS (Consejo Nacional de Tecnología de la Información).
Normas). J3 actúa como el organismo de desarrollo para el grupo internacional correspondiente, WG5,
compuesto por expertos internacionales responsables de recomendar la elección de características.
J3 mantiene otros contactos cercanos con la comunidad internacional dando la bienvenida a extranjeros
miembros, incluidos los autores actuales durante muchos años.
¿Cuáles fueron las justificaciones para continuar revisando la definición del idioma Fortran?
Además de estandarizar las extensiones de proveedor, era necesario modernizarlo en respuesta
a los desarrollos en el diseño del lenguaje que habían sido explotados en otros idiomas, como
APL, Algol 68, Pascal, Ada, C y C ++. Aquí, J3 podría aprovechar los beneficios obvios de
conceptos como el ocultamiento de datos. En la misma línea estaba la necesidad de comenzar a proporcionar una
alternativa.
a la asociación de almacenamiento peligroso, para abolir la rigidez de la forma de fuente anticuada, y
para mejorar aún más la regularidad del idioma, así como para aumentar la seguridad de
programación en el lenguaje y para ajustar los requisitos de conformidad. Para preservar
Después de la gran inversión en el código Fortran 77, todo Fortran 77 se mantuvo como un subconjunto.
Sin embargo, a diferencia del estándar anterior, que resultó casi por completo de un esfuerzo por
estandarizar las prácticas existentes, el estándar Fortran 90 fue mucho más un desarrollo de
el lenguaje, presentando características que eran nuevas para Fortran pero que se basaban en la experiencia
en otros idiomas
Las características principales de Fortran 90 fueron, ante todo, el lenguaje de matriz y los datos
abstracción. El primero se basa en operaciones y asignaciones de matriz completa, secciones de matriz,
procedimientos intrínsecos para matrices y almacenamiento dinámico. Fue diseñado con optimización
en mente. La abstracción de datos se basa en módulos y procedimientos de módulos, tipos de datos derivados,
sobrecarga del operador e interfaces genéricas, junto con punteros. También fueron importantes
las nuevas facilidades para el cálculo numérico, que incluyen un conjunto de funciones de consulta numérica,
la parametrización de los tipos intrínsecos, nuevas construcciones de control como el caso de selección
y nuevas formas de hacer, procedimientos internos y recursivos, argumentos opcionales y de palabras clave,
instalaciones mejoradas de E / S y muchos procedimientos intrínsecos nuevos. Por último, pero no menos importante,
fueron los
nuevo formulario de fuente libre, un estilo mejorado de especificaciones orientadas a atributos, lo implícito
ninguna declaración, y un mecanismo para identificar características redundantes para su posterior eliminación
del idioma El requisito de los compiladores para poder identificar, por ejemplo,
Las extensiones de sintaxis, y para informar por qué un programa ha sido rechazado, también son importantes. los
el lenguaje resultante no solo era una herramienta mucho más poderosa que su predecesor, sino que era más seguro y
más confiable también. La asociación de almacenamiento, con sus peligros asociados, no fue abolida,
pero hecho innecesario De hecho, la experiencia mostró que los compiladores detectaron errores lejos
con mayor frecuencia que antes, lo que resulta en un ciclo de desarrollo más rápido. La sintaxis de matriz y
La recursión también permitió que se escribiera un código bastante compacto, una ayuda adicional para una programación
segura.
1.4 Evolución del lenguaje
Los procedimientos bajo los cuales J3 funciona requieren que se dé un período de aviso antes de cualquier
la función existente se elimina del idioma. Esto significa, en la práctica, un mínimo de
un ciclo de revisión, que para Fortran es de al menos cinco años. La necesidad de eliminar características es
evidente: si la única acción del comité es agregar nuevas características, el lenguaje se convertirá

Página 2
4 Fortran moderno explicado
grotescamente grande, con muchos elementos superpuestos y redundantes. La solución finalmente adoptada
por J3 fue publicar como un apéndice a un estándar un conjunto de dos listas que muestran qué elementos tienen
han sido eliminados o son candidatos para una eventual eliminación.
Una lista contiene las características eliminadas, las que se han eliminado. Desde Fortran 90
contenía todo Fortran 77, esta lista estaba vacía para Fortran 90. También estaba vacía para
Fortran 2008 pero no era para los demás, véanse los Apéndices B.4 a B.6.
La segunda lista contiene las características obsoletas, las que se consideran anticuadas y
redundante, y que son candidatos para su eliminación en la próxima revisión. Esta lista estaba vacía para
Fortran 2008 pero no era para los demás, véanse los Apéndices B.1 a B.3.
Además del control de carro (Apéndice B.5), las funciones eliminadas aún son compatibles
por la mayoría de los compiladores debido a la demanda de viejos programas probados para continuar
trabajo. Por lo tanto, el concepto de obsolescencia realmente no funciona según lo previsto, pero al menos da
una señal clara de que ciertas funciones están pasadas de moda y que deben evitarse en nuevos programas y
No se les enseñará a nuevos programadores.
1.5 Fortran 95
Tras la publicación del estándar Fortran 90 en 1991, dos más importantes
ocurrieron desarrollos relacionados con el lenguaje Fortran. El primero fue el continuo
operación de los dos comités de normas de Fortran, J3 y WG5, y el segundo fue el
Fundación del Foro Fortran de Alto Rendimiento (HPFF).
Al principio de sus deliberaciones, los comités de normas decidieron una estrategia mediante la cual
una revisión menor de Fortran 90 se prepararía a mediados de la década de 1990 y una revisión mayor por
sobre el año 2000. La primera revisión, Fortran 95, es el tema de la primera parte de este libro.
El HPFF se creó en un esfuerzo por definir un conjunto de extensiones a Fortran para que sea posible
escribir código portátil cuando se usan computadoras paralelas para manejar problemas que involucran grandes
conjuntos de datos que pueden representarse mediante cuadrículas regulares. Esta versión de Fortran debía ser conocida
como High Performance Fortran (HPF), y se decidió rápidamente, dadas las características de la matriz de
Fortran 90, que, y no Fortran 77, debería ser su idioma base. La forma final de HPF 1
fue un superconjunto de Fortran 90, las extensiones principales se dieron en forma de directivas que toman
la forma de las líneas de comentarios de Fortran 90, y por lo tanto son reconocidas como directivas solo por un HPF
procesador. Sin embargo, también se hizo necesario agregar alguna sintaxis adicional, ya que no todas
las características deseadas podrían acomodarse en forma de tales directivas.
El trabajo de J3 y WG5 continuó al mismo tiempo que el de HPFF, y los cuerpos se pusieron en contacto
cercanamente. Era evidente que, para evitar el desarrollo de dialectos divergentes de Fortran,
Sería deseable incluir la nueva sintaxis definida por HPFF en Fortran 95 y, de hecho,
Las características de HPF fueron sus nuevas características más importantes. Más allá de esto, un pequeño número de
otros
se realizaron cambios de idioma urgentes pero menores, principalmente basados en la experiencia con el uso de
Fortran 90.
Los detalles de Fortran 95 se finalizaron en 1995, y el nuevo estándar ISO, que reemplazó
Fortran 90, fue adoptado en 1997, luego de votaciones exitosas, como ISO / IEC 1539-1: 1997.
1 The High Performance Fortran Handbook, C. Koebel et al., MIT Press, Cambridge, MA, 1994.

Página 3
¿De dónde viene Fortran? 5 5
1.6 Extensiones a Fortran 95
Poco después de la publicación de Fortran 90, se estableció un estándar auxiliar para cadenas de longitud variable
desarrollado. Una minoría sintió que esto debería haber sido parte de Fortran 90, pero quedó satisfecha
con esta alternativa El estándar auxiliar define la interfaz y la semántica de un módulo.
que proporciona facilidades para la manipulación de cadenas de caracteres de forma arbitraria y dinámica
Longitud variable. Se ha revisado para Fortran 95 como ISO / IEC 1539-2: 2000 (E). Un anexo
hizo referencia a una posible implementación 2 en Fortran 95, que demostró su viabilidad. los
la intención era que los proveedores brinden características equivalentes que se ejecuten de manera más eficiente pero, en
De hecho, eso nunca sucedió.
Además, en 1995, WG5 decidió que tres características,
• permitir matrices asignables como componentes de estructura, argumentos ficticios y función
resultados,
• manejo de excepciones de punto flotante, y
• interoperabilidad con C,
se necesitaban con tanta urgencia en Fortran que estableció organismos de desarrollo para desarrollar
'Informes técnicos del tipo 2'. La intención era que el material de estos informes técnicos
implementarse como extensiones de Fortran 95 e integrarse en la próxima revisión del
estándar, aparte de cualquier defecto encontrado en el campo. Era esencialmente una instalación de prueba beta
para una función de lenguaje. En el caso, se completaron los dos primeros informes, pero no el tercero.
El primero se implementó ampliamente en los compiladores Fortran 95. Las características de los dos informes.
se incorporaron en Fortran 2003. Si bien no hubo un informe para el tercero, las características para
la interoperabilidad con C se incluyó en Fortran 2003. En este libro, los tres temas son
incluidos en los capítulos 6, 18 y 19, respectivamente.
1.7 Fortran 2003
La próxima revisión completa del idioma se publicó en noviembre de 2004 y se conoce como
Fortran 2003 ya que los detalles se finalizaron en 2003. A diferencia de Fortran 95, fue un importante
revisión, sus principales novedades son:
• Mejoras de tipo derivado: tipos derivados parametrizados, control mejorado de
accesibilidad, constructores de estructuras mejoradas y finalizadores.
• Soporte de programación orientada a objetos: extensión de tipo y herencia, polimorfismo,
asignación dinámica de tipos y procedimientos de tipo vinculado.
• Mejoras en la manipulación de datos: componentes asignables, parámetros de tipo diferido,
atributo volátil, especificación de tipo explícito en constructores de matrices y asignación
declaraciones, mejoras de puntero, expresiones de inicialización extendidas (ahora llamadas
expresiones constantes) y procedimientos intrínsecos mejorados.
2 ftp://ftp.nag.co.uk/sc22wg5/ISO_VARYING_STRING/

Página 4
6 Fortran moderno explicado
• Mejoras de entrada / salida: transferencia asíncrona, acceso a flujo, especificado por el usuario
operaciones de transferencia para tipos derivados, control de redondeo especificado por el usuario durante
conversiones de formato, constantes con nombre para unidades preconectadas, la instrucción flush,
regularización de palabras clave y acceso a mensajes de error.
• Punteros de procedimiento.
• Soporte de excepciones IEC 60559 (IEEE 754).
• Interoperabilidad con el lenguaje de programación C.
• Soporte para uso internacional: acceso a caracteres de cuatro bytes ISO 10646 y elección
de coma decimal o coma en E / S con formato numérico.
• Integración mejorada con el sistema operativo host: acceso a la línea de comando
argumentos, variables de entorno y mensajes de error del procesador.
1.8 Extensiones a Fortran 2003
Se decidió en 2001 que una característica para abordar problemas con el mantenimiento de muy
los módulos grandes eran demasiado importantes para retrasar la próxima revisión y deberían ser el tema
de otro informe técnico. Esto se completó en 2005 como ISO / IEC TR 19767: 2005 y
define submódulos, ver Capítulo 16. Desafortunadamente, hubo pocas implementaciones tempranas.
Las características de interoperabilidad en Fortran 2003 proporcionan un mecanismo para compartir datos
entre Fortran y C, pero aún era necesario que los usuarios implementaran una capa de traducción
para un procedimiento con un argumento que es opcional, un puntero, asignable o de forma asumida.
Se decidió que agregar características para abordar esto era demasiado importante como para esperar el próximo
revisión y así fue objeto de otro informe técnico. El trabajo comenzó en 2006 pero
resultó más difícil de lo esperado y no se completó hasta 2012, por lo que no estaba listo para
incorporación en el próximo estándar, Fortran 2008. Apareció como ISO / IEC TS 29113: 2012 y
está incorporado en Fortran 2018. Mientras tanto, ISO / IEC había renombrado estos informes como Técnicos
Especificaciones, pero la intención no cambió.
1.9 Fortran 2008
A pesar del hecho de que los compiladores para Fortran 2003 tardaron en aparecer, el
los comités de estandarización pensaron que era apropiado sumergirse en otro estándar. Fue pensado
para ser una pequeña revisión, pero se hizo evidente que la programación paralela iba a ser
universal, por lo que se agregaron conjuntos de secuencias y fueron su nueva característica más importante. Promover,
adicional,
Se introdujo la forma concurrente de control de bucle y el atributo contiguo. los
Se agregó la función de submódulo, prometida por el Informe técnico mencionado en la Sección 1.8.
Otras características nuevas incluyen varias mejoras de datos, acceso mejorado a objetos de datos,
mejoras en E / S y control de ejecución, y procedimientos más intrínsecos, en particular
para procesamiento de bits.
Fortran 2008 se publicó en octubre de 2010.

Página 5
¿De dónde viene Fortran? 7 7
1.10 Extensiones a Fortran 2008
Para evitar que la extensión de Fortran 2003 a Fortran 2008 se vuelva muy grande y acelerar
de acuerdo con todos los detalles, WG5 decidió diferir algunas de las características de la matriz a un
Especificación técnica. En cuanto a los informes técnicos, se pretendía que el material
implementarse como extensiones de Fortran 2008 e integrarse en la próxima revisión, además de
Cualquier defecto encontrado en el campo. El trabajo no comenzó hasta 2011 y se completó en 2015 como
ISO / IEC TS 18508: 2015. Las características se describen en el Capítulo 20.
1.11 Fortran 2018
Fortran 2018 es una extensión menor de Fortran 2008. Las características fueron elegidas en 2015 y el
el idioma se llamaba originalmente Fortran 2015. Finalmente se decidió seguir el más habitual
práctica de nombrar la versión por su fecha de publicación; esto da la impresión de que el
La diferencia con la versión anterior es mayor de lo que realmente es.
Los principales cambios se refieren a las características definidas en las especificaciones técnicas para más
funciones de matriz, consulte el Capítulo 20, y una mayor interoperabilidad con C, consulte el Capítulo 21. Más allá
estos, hay una gran cantidad de pequeñas mejoras, véanse los capítulos 22 y 23.
1.12 Conformidad
Las normas se refieren casi exclusivamente a las reglas para los programas más que a las
procesadores Se requiere un procesador para aceptar un programa conforme a la norma y para
interpretarlo de acuerdo con el estándar, sujeto a los límites que el procesador puede imponer
tamaño y complejidad del programa. El procesador puede aceptar más sintaxis y
interpretar relaciones que no están especificadas en el estándar, siempre que no entren en conflicto con
el estandar. En muchos lugares de este libro decimos '. . . no esta permitido'. Con esto queremos decir que
no está permitido en un programa conforme a la norma. Sin embargo, una implementación puede
permitirlo como una extensión. Por supuesto, el programador debe evitar tales extensiones de sintaxis si
se desea portabilidad.
La interpretación de parte de la sintaxis estándar depende del procesador, es decir, puede
variar de procesador a procesador. Por ejemplo, el conjunto de caracteres permitidos en el personaje
cadenas depende del procesador. Se debe tener cuidado siempre que una función dependiente del procesador
se usa en caso de que el programa no sea portátil a un procesador deseado.
Un inconveniente del estándar Fortran 77 fue que no hizo ninguna declaración acerca de requerir
procesadores para proporcionar un medio para detectar cualquier desviación de la sintaxis permitida por un programa,
siempre que esa partida no entre en conflicto con las reglas de sintaxis definidas por el estándar. los
Los nuevos estándares están escritos en un estilo diferente. Las reglas de sintaxis se expresan en una variante de
BNF 3 con restricciones asociadas, y la semántica se describe en el texto. Este semi-
el estilo formal no se usa en este libro, por lo que un ejemplo, de Fortran 95, quizás sea útil:
3 Forma Backus-Naur, una notación utilizada para describir la sintaxis de un lenguaje de computadora.

Página 6
8 Fortran moderno explicado
Subcadena R609
es
cadena principal (rango de subcadena)
Cadena principal R610
es
nombre-variable-escalar
o elemento de matriz
o componente de estructura escalar
o constante escalar
El rango de subcadena R611 es
[scalar-int-expr]: [scalar-int-expr]
Restricción: la cadena principal debe ser de tipo carácter.
El valor del primer scalar-int-expr en el substring-range se denomina inicio
punto y el valor del segundo se llama el punto final. La longitud de un
subcadena es el número de caracteres en la subcadena y es MAX (l− f +1,0),
donde f y l son los puntos inicial y final, respectivamente.
Aquí, las tres reglas de producción y la restricción asociada para una subcadena de caracteres son
definido y explicado el significado de la longitud de dicha subcadena.
Los estándares están escritos de tal manera que un procesador, en el momento de la compilación, puede verificar
que el programa satisface todas las restricciones. En particular, el procesador debe proporcionar un
capacidad para detectar e informar el uso de cualquier
• característica obsoleta;
• sintaxis adicional;
• parámetro de tipo amable (Sección 2.5) que no admite;
• forma o carácter fuente no estándar;
• nombre que es inconsistente con las reglas de alcance; o
• procedimiento intrínseco no estándar.
Además, debe poder informar el motivo por el que se rechaza un programa. Estas capacidades
son de gran valor para producir código correcto y portátil.

Página 7

2. Elementos del lenguaje.


2.1 Introducción
La prosa escrita en un idioma natural, como un texto en inglés, se compone en primer lugar de
elementos: las letras del alfabeto. Estos se combinan en entidades más grandes, palabras,
que transmiten los conceptos básicos de objetos, acciones y calificaciones. Las palabras de
el lenguaje se puede combinar en unidades más grandes, frases y oraciones, según
a ciertas reglas. Un conjunto de reglas define la gramática. Esto nos dice si cierto
la combinación de palabras es correcta porque se ajusta a la sintaxis del lenguaje; es decir,
aquellas formas reconocidas que se consideran representaciones correctas de los significados que deseamos
para expresar. Las oraciones a su vez se pueden unir en párrafos, que convencionalmente
contienen el significado compuesto de sus oraciones constituyentes, cada párrafo expresa un
Unidad de información más grande. En una novela, las secuencias de párrafos se convierten en capítulos y el
los capítulos juntos forman un libro, que generalmente es una obra independiente, en gran parte independiente
de todos los otros libros.
2.2 Conjunto de caracteres Fortran
Las analogías a estos conceptos se encuentran en un lenguaje de programación. En Fortran, lo básico
elementos, o conjunto de caracteres, son las 26 letras del alfabeto inglés, tanto en mayúsculas como en letras
minúscula, los diez números arábigos, 0 a 9, el guión bajo, _ y el llamado especial
caracteres enumerados en la tabla 2.1. Dentro de la sintaxis de Fortran, las letras minúsculas son equivalentes
a las letras mayúsculas correspondientes; se distinguen solo cuando forman parte de un
secuencia de caracteres En este libro, siempre se escribirán caracteres sintácticamente significativos
en minúsculas Las letras, números y guiones bajos se conocen como caracteres alfanuméricos.
Excepto por el símbolo de la moneda, cuyo gráfico puede variar (por ejemplo, £ en los Estados Unidos
Kingdom), los gráficos son fijos, aunque sus estilos no son fijos. Como se muestra en la Tabla 2.1,
Algunos de los caracteres especiales no tienen un significado específico dentro del lenguaje Fortran.
En el curso de este y los siguientes capítulos veremos cómo más analogías con
Se puede dibujar un lenguaje natural. La unidad de información de Fortran es la ficha léxica, que
corresponde a una palabra o signo de puntuación. Las fichas adyacentes generalmente están separadas por espacios
o al final de una línea, pero se permiten excepciones razonables como para un signo de puntuación en
prosa. Las secuencias de tokens forman declaraciones, correspondientes a oraciones. Declaraciones, como
oraciones, se pueden unir para formar unidades más grandes como párrafos. En Fortran estos son conocidos
como unidades de programa, y de ellas se puede construir un programa. Un programa forma un completo
Fortran moderno explicado, 2da edición. Michael Metcalf, John Reid y Malcolm Cohen. prensa de la Universidad de Oxford
(2018) cG Michael Metcalf, John Reid y Malcolm Cohen 2018. DOI 10.1093 / oso / 9780198811893.001.0001

Página 8
10 Fortran moderno explicado
Tabla 2.1. Los caracteres especiales de la lengua Fortran.
Significado sintáctico
Significado sintáctico
Sin significado sintáctico
= Signo igual
: Colon
\ Backslash
+ Signo más
Blanco
$ Símbolo de moneda
- Signo menos
! Signo de exclamación
? Signo de interrogación
* Asterisco
% Por ciento
{Soporte rizado izquierdo
/ Slash
& Ampersand
} Soporte rizado derecho
(Paréntesis izquierdo
; Punto y coma
~ Tilde
) Paréntesis derecho
<Menos de
' Acento grave
[Corchete izquierdo
> Mayor que
^ Acento circunflejo
] Corchete derecho
«Apóstrofe
El | Linea vertical
, Coma
"Comillas
# Símbolo de número
. Punto decimal
@ Comercial en
conjunto de instrucciones a una computadora para llevar a cabo una secuencia definida de operaciones. Lo más simple
el programa puede consistir en solo unas pocas declaraciones, pero los programas de más de 100 000 declaraciones
Ahora son bastante comunes.
2.3 fichas
Dentro del contexto de Fortran, los caracteres alfanuméricos (las letras, el guión bajo y el
números) pueden combinarse en secuencias que tienen uno o más significados. Por ejemplo,
Uno de los significados de la secuencia 999 es una constante en el sentido matemático. Similar,
la fecha de secuencia podría representar, como una posible interpretación, una cantidad variable para
que le asignamos la fecha del calendario.
Los caracteres especiales se utilizan para separar tales secuencias y también tienen varios significados.
Veremos cómo se usa el asterisco para especificar la operación de multiplicación, como en x * y, y
También tiene una serie de otras interpretaciones.
Se hace referencia a secuencias significativas básicas de caracteres alfanuméricos o de caracteres especiales.
como tokens; son etiquetas, palabras clave, nombres, constantes (que no sean literales complejos
constantes), operadores (enumerados en la Tabla 3.4, Sección 3.9) y separadores, que son
//
(
)
[
]
(/
/)
,
=
=>
:
:: ::
;
%
Por ejemplo, la expresión x * y contiene los tres tokens x, * e y.
Además de dentro de una cadena de caracteres o dentro de un token, los espacios en blanco se pueden usar libremente
para
mejorar el diseño Por lo tanto, mientras que la fecha variable no puede escribirse como fecha,
la secuencia x * y es sintácticamente equivalente a x * y. En este contexto, hay varios espacios en blanco
sintácticamente equivalente a un solo espacio en blanco.
Un nombre, constante o etiqueta se debe separar de una palabra clave adyacente, nombre, constante,
o etiquetar con uno o más espacios en blanco o al final de una línea. Por ejemplo, en

Página 9
Elementos del lenguaje 11
x real
rebobinar 10
30 do k = 1,3
los espacios en blanco son necesarios después de real, rewind, 30 y do. Del mismo modo, las palabras clave adyacentes
deben
normalmente se separan, pero algunos pares de palabras clave, como else if, no están obligados a
estar separado Del mismo modo, algunas palabras clave pueden dividirse; por ejemplo, inout puede escribirse
En fuera. No utilizamos estas alternativas, pero las reglas exactas se dan en la Tabla 2.2.
Tabla 2.2. Palabras clave adyacentes donde la separación de espacios en blanco es opcional.
bloquear datos
doble precisión si no
otro lugar donde
asociado final
bloque final
final de bloque de datos final crítico
fin hacer
fin de enumeración
archivo final
fin para todos
función final
terminara si
interfaz final
módulo final
procedimiento final
programa final
seleccione final
submódulo final
subrutina final tipo final
termina donde
ir
En fuera
seleccione el caso
seleccione tipo
2.4 Formulario fuente
Las declaraciones de las que se compone un programa fuente están escritas en líneas. Cada línea puede
contiene hasta 132 caracteres, 1 y generalmente contiene una sola declaración. Desde espacios principales
no son significativos, es posible comenzar todas esas declaraciones en la posición del primer carácter, o en
cualquier otra posición consistente con el diseño elegido por el usuario. Por lo tanto, se puede escribir una declaración
como
x = (-y + root_of_discriminant) / (2.0 * a)
Para poder mezclar comentarios adecuados con el código al que se refieren, Fortran
permite que cualquier línea lleve un campo de comentario final, después de un signo de exclamación (!). Un
ejemplo es
x=y/a-b
! Resolver la ecuación lineal.
Cualquier comentario siempre se extiende hasta el final de la línea de origen y puede incluir procesador-
caracteres dependientes (no está restringido al conjunto de caracteres Fortran, Sección 2.2). Cualquier linea
cuyo primer carácter no en blanco es un signo de exclamación, o que contiene solo espacios en blanco, o
que está vacío, es puramente comentario e ignorado por el compilador. Tales líneas de comentarios
puede aparecer en cualquier lugar de una unidad de programa, incluso antes de la primera declaración e incluso después
La unidad final del programa. Un contexto de caracteres (aquellos contextos definidos en las Secciones 2.6.4 y
11.2) se permite contener!, Por lo que el! no inicia un comentario en este caso; en todos los demás
casos lo hace.
Dado que es posible que una declaración larga no se acomode en las 132 posiciones
permitido en una sola línea, se permiten hasta 255 líneas de continuación adicionales. 2 Los llamados
1 Las líneas que contienen caracteres de tipo no predeterminado (Sección 2.6.4) están sujetas a un límite dependiente del procesador.
2 Tales declaraciones largas pueden generarse automáticamente.

Página 10
12 Fortran moderno explicado
la marca de continuación es el carácter de y comercial (&), y esto se agrega a cada línea que es
seguido de una línea de continuación. Por lo tanto, la primera declaración de esta sección (considerablemente espaciada
fuera) podría escribirse como
x=
Y
(-y + root_of_discriminant)
Y
/(2.0*a)
En este libro, los símbolos de unión normalmente se alinearán para mejorar la legibilidad. En un no
línea de comentario, si & es el último carácter no en blanco o el último carácter no en blanco delante de
el símbolo de comentario!, la declaración continúa del carácter inmediatamente anterior
el &. La continuación es normalmente al primer carácter de la siguiente línea sin comentarios, pero si el
el primer carácter no en blanco de la siguiente línea sin comentarios es &, la continuación es para el carácter
siguiendo el &. Por ejemplo, la declaración anterior puede estar escrita
x=
Y
& (- y + root_of_discriminant) / (2.0 * a)
En particular, si un token no puede estar contenido al final de una línea, el primer carácter no en blanco
en la siguiente línea sin comentarios debe ser & seguido inmediatamente por el resto del
simbólico.
Los comentarios pueden contener caracteres, incluidos &, por lo que no pueden continuar
porque un & final se toma como parte del comentario. Sin embargo, las líneas de comentarios pueden ser libremente
intercalados entre líneas de continuación y no cuentan hacia el límite de 255 líneas.
En un contexto de caracteres, la continuación debe ser desde una línea sin un comentario final y para
una línea con un líder comercial. Esto es porque ambos! y & están permitidos tanto en carácter
contextos y en comentarios.
No se permite que ninguna línea tenga & como su único carácter no en blanco, o como su único no en blanco
personaje por delante! Tal línea es realmente un comentario y se convierte en un comentario si se elimina &.
Puede ser conveniente escribir varias declaraciones en una línea. El carácter de punto y coma (;)
siempre se puede usar como un separador de instrucciones, por ejemplo:
a = 0; b = 0; c = 0
pero no debe aparecer como el primer carácter no en blanco de una línea a menos que sea una línea de continuación.
Los punto y coma adyacentes, posiblemente separados por espacios en blanco, se interpretan como uno.
Como los comentarios siempre se extienden hasta el final de la línea, no es posible insertar
comentario entre declaraciones en una sola línea. En principio, es posible escribir varios
declaraciones largas una tras otra en un bloque sólido de líneas, cada una de 132 caracteres de longitud y
con los puntos y comas apropiados que separan las declaraciones individuales. En la práctica, dicho código
es ilegible, y el uso de líneas de enunciados múltiples debe reservarse para casos triviales como
como el que se muestra en este ejemplo.
Cualquier declaración de Fortran (que no sea parte de una declaración compuesta) puede etiquetarse, en orden
para poder identificarlo. Para algunas declaraciones, una etiqueta es obligatoria. Una etiqueta de declaración precede
la declaración, y se considera como una ficha. La etiqueta consta de uno a cinco dígitos, uno de
que debe ser distinto de cero. Un ejemplo de una declaración etiquetada es
100 continuar
Los ceros iniciales no son significativos para distinguir entre etiquetas. Por ejemplo, 10 y 010
son equivalentes

Página 11
Elementos del lenguaje 13
2.5 Concepto de tipo
En Fortran es posible definir y manipular varios tipos de datos. Por ejemplo, podemos
tener disponible el valor 10 en un programa y asignar ese valor a una variable escalar entera
denotado por i. Tanto 10 como i son de tipo entero; 10 es un valor fijo o constante, mientras que
i es una variable a la que se le pueden asignar otros valores. Las expresiones enteras, como i + 10, son
disponible también
Un tipo de datos consta de un conjunto de valores de datos, un medio para denotar esos valores y
un conjunto de operaciones que están permitidas en ellos. Para el tipo de datos entero, los valores son
..., - 3, -2, -1,0,1,2,3, ... entre algunos límites dependiendo del tipo de entero y
Sistema informático utilizado. Tales tokens como estos son constantes literales y cada tipo de datos
tiene su propia forma de expresarlos. Se pueden establecer variables escalares con nombre, como i.
Durante la ejecución de un programa, el valor de i puede cambiar a cualquier valor válido, o puede
quedar indefinido, es decir, no tener un valor predecible. Las operaciones que se pueden realizar.
los enteros son los de la aritmética habitual; podemos escribir 1 + 10 o i-3 y obtener el esperado
resultados. También se pueden establecer constantes con nombre; estos tienen valores que no cambian durante
ejecución del programa.
Las propiedades como las que acabamos de mencionar están asociadas con todos los tipos de datos de Fortran, y
se describirá en detalle en este y los siguientes capítulos. El lenguaje en sí contiene cinco
tipos de datos cuya existencia siempre se puede suponer. Estos se conocen como los tipos intrínsecos,
cuyas constantes literales forman el tema de la siguiente sección. De cada tipo intrínseco hay un
tipo predeterminado y un número de otros tipos dependiente del procesador. Cada tipo está asociado con
un valor entero no negativo conocido como parámetro de tipo amable. Esto se usa como un medio de
identificando y distinguiendo los diversos tipos disponibles.
Además, es posible definir otros tipos de datos basados en colecciones de datos de
tipos intrínsecos, y estos se conocen como tipos derivados. La capacidad de definir tipos de datos de
interés para el programador - matrices, formas geométricas, listas, números de intervalo - es un
potente característica del lenguaje, que permite un alto nivel de abstracción de datos, es decir
la capacidad de definir y manipular objetos de datos sin preocuparse por su real
representación en una computadora.
2.6 Constantes literales de tipo intrínseco
Los tipos de datos intrínsecos se dividen en dos clases. La primera clase contiene tres números.
tipos que se utilizan principalmente para cálculos numéricos: entero, real y complejo. los
la segunda clase contiene los dos tipos no numéricos que se utilizan para aplicaciones como
Procesamiento de texto y control de programa - carácter y lógica. Los tipos numéricos se utilizan en
junto con los operadores habituales de aritmética, como + y -, que se describirán
en el Capítulo 3. Cada uno incluye un cero, y el valor de un cero con signo es el mismo que el de un
cero sin signo 3 Los tipos no numéricos se utilizan con conjuntos de operadores específicos para cada tipo;
por ejemplo, los datos de caracteres pueden estar concatenados. Estos también se describirán en el Capítulo 3.
3 Aunque la representación de datos depende del procesador, para los tipos de datos numéricos el estándar define
representaciones de modelos y medios para preguntar sobre las propiedades de esos modelos. Los detalles se difieren a
Sección 9.9.

Pagina 12
14 Fortran moderno explicado
2.6.1 Constantes literales enteras
El primer tipo de constante literal es la constante literal entera. El tipo predeterminado es simplemente un
valor entero con signo o sin signo, por ejemplo:
1
00
-999
32767
+10
El rango de los enteros predeterminados no se especifica en el idioma, sino en una computadora con
un tamaño de palabra de n bits, a menudo es de -2 n-1 a +2 n-1 - 1. Por lo tanto, en una computadora de 32 bits
el rango es a menudo de -2 147 483 648 a +2 147 483 647. Sin embargo, el tamaño entero máximo
se requiere tener un rango de al menos 18 dígitos decimales, lo que implica, en una máquina binaria (todo
computadoras modernas), un entero de 64 bits.
Para asegurarse de que el rango sea adecuado en cualquier computadora, se requiere la especificación de
el tipo de entero dando un valor para el parámetro de tipo amable. Esto se hace mejor a través de un
constante entera llamada Por ejemplo, si se desea el rango -999999 a 999999, k6 puede
establecerse como una constante con un valor apropiado por la declaración, explicada completamente más adelante,
entero, parámetro :: k6 = selected_int_kind (6)
y usado en constantes así:
-123456_k6
+ 1_k6
2_k6
Aquí, selected_int_kind (6) es una llamada de función de consulta intrínseca, y devuelve un tipo
valor del parámetro que produce el rango -999 999 a 999 999 con el menor margen (ver
Sección 9.9.4).
En un procesador dado, se puede saber que el valor de tipo necesario es 3. En este caso, el
primero de nuestras constantes se puede escribir
-123456_3
Pero esta forma es menos portátil. Si movemos el código a otro procesador, este valor particular
puede no ser compatible o puede corresponder a un rango diferente.
Muchas implementaciones usan valores amables que indican la cantidad de bytes de almacenamiento
ocupado por un valor, pero el estándar permite una mayor flexibilidad. Por ejemplo, un procesador
podría tener hardware solo para enteros de cuatro bytes y, sin embargo, admitir valores de tipo 1, 2 y 4 con
este hardware (para facilitar la portabilidad de los procesadores que tienen hardware para uno, dos y cuatro)
bytes enteros). Sin embargo, el estándar no hace ninguna declaración sobre los valores amables o su orden,
excepto que el valor amable nunca es negativo.
El valor del parámetro de tipo amable para un tipo de datos determinado en un procesador determinado puede ser
obtenido de la función intrínseca amable (Sección 9.2):
tipo (1)
! para el valor predeterminado
tipo (2_k6)
! por el ejemplo

Página 13
Elementos del lenguaje 15
y el rango de exponente decimal (número de dígitos decimales admitidos) de una entidad dada puede
ser obtenido de otra función (Sección 9.9.2), como en
rango (2_k6)
que en este caso devolvería un valor de al menos 6.
2.6.2 Constantes literales reales
El segundo tipo de constante literal es la constante literal real. El tipo predeterminado es un flotante
forma de punto construida de parte o la totalidad de una parte entera con signo o sin signo, un punto decimal, un
parte fraccionaria y una parte exponente con signo o sin signo. Uno o ambos de la parte entera y
la parte fraccionaria debe estar presente. La parte exponente está ausente o consiste en la letra e
seguido de un entero con o sin signo. Uno o ambos del punto decimal y el exponente
parte debe estar presente. Un ejemplo es
-10,6e-11
significa −10.6 × 10 −11 , y otras formas legales son
1)
-0,1
1e-1
3.141592653
Las constantes literales reales predeterminadas son representaciones de un subconjunto de los números reales de
matemáticas, y el estándar no especifica ni el rango permitido del exponente ni el
Número de dígitos significativos representados por el procesador. Muchos procesadores se ajustan a
Estándar IEEE para aritmética de coma flotante y tiene valores de 10 −37 a 10 +37 para el rango,
y una precisión de seis dígitos decimales.
Para garantizar la obtención de un rango y precisión deseados se requiere la especificación de un tipo
valor del parámetro Por ejemplo,
entero, parámetro :: largo = selected_real_kind (9, 99)
asegura que las constantes
1.7_de largo
12.3456789e30_long
tener una precisión de al menos nueve decimales significativos y un rango de exponente de al menos 10 −99
a 10 +99 . El número de dígitos especificado en el significado no tiene ningún efecto sobre el tipo. En
En particular, está permitido escribir más dígitos de los que el procesador puede utilizar.
En cuanto a los enteros, muchas implementaciones usan valores amables que indican el número de bytes de
almacenamiento ocupado por un valor, pero el estándar permite una mayor flexibilidad. Solo especifica que
El valor amable nunca es negativo. Si se conoce el valor de tipo deseado, puede usarse directamente,
como en el caso
1.7_4
pero el código resultante es menos portátil.
El procesador debe proporcionar al menos una representación con más precisión que la predeterminada,
y esta segunda representación también puede especificarse como doble precisión. Diferimos el
Descripción de esta sintaxis alternativa pero anticuada del Apéndice A.6.
La función kind es válida también para valores reales:

Página 14
16 Fortran moderno explicado
tipo (1.0)
! para el valor predeterminado
tipo (1.0_long)
! por el ejemplo
Además, hay dos funciones de consulta disponibles que devuelven la precisión real y
rango, respectivamente, de una entidad real dada (ver Sección 9.9.2). Por lo tanto, el valor de
precisión (1.7_long)
sería al menos 9, y el valor de
rango (1.7_long)
sería al menos 99.
2.6.3 Constantes literales complejas
Fortran, como lenguaje destinado a cálculos científicos y de ingeniería, tiene la ventaja
de tener como tercera constante literal, escriba la constante literal compleja. Esto es designado por un
par de constantes literales, que son enteras o reales, separadas por una coma y encerradas
entre paréntesis. Ejemplos son
(1., 3.2)
(1, .99e-2)
(1.0, 3.7_8)
donde la primera constante de cada par es la parte real del número complejo, y la segunda
constante es la parte imaginaria. Si una de las partes es entera, el tipo de constante compleja
es el de la otra parte. Si ambas partes son enteras, el tipo de constante es la del valor predeterminado
tipo real Si ambas partes son reales y del mismo tipo, este es el tipo de constante. Si ambos
las partes son reales y de diferentes tipos, el tipo de constante es el de una de las partes: el
parte con la mayor precisión decimal, o la parte elegida por el procesador si el decimal
Las precisiones son idénticas.
Una constante compleja predeterminada es aquella cuyo valor de tipo es el real predeterminado.
Las funciones kind, precision y range son igualmente válidas para entidades complejas.
Tenga en cuenta que si una implementación usa el número de bytes necesarios para almacenar un real como su tipo
valor, el número de bytes necesarios para almacenar un valor complejo del tipo correspondiente es
el doble del valor amable Por ejemplo, si el tipo real predeterminado tiene el tipo 4 y necesita cuatro bytes de
almacenamiento, el tipo complejo predeterminado tiene el tipo 4 pero necesita ocho bytes de almacenamiento.
2.6.4 Constantes literales de caracteres
El cuarto tipo de constante literal es la constante literal de caracteres. El tipo predeterminado consiste
de una cadena de caracteres encerrados en un par de apóstrofes o comillas, por
ejemplo
'Todo vale'
"Tuercas y tornillos"
Los personajes no están restringidos al conjunto Fortran (Sección 2.2). Cualquier personaje gráfico
el procesador lo admite, pero no los caracteres de control como 'nueva línea'. los
los apóstrofes y las comillas sirven como delimitadores, y no son parte del valor de
constante. El valor de la constante.
Página 15
Elementos del lenguaje 17
'CUERDA'
es STRING Tenga en cuenta que en las constantes de caracteres, el carácter en blanco es significativo. Por ejemplo
'una cuerda'
no es lo mismo que
'una cuerda'
Un problema surge con la representación de un apóstrofe o una comilla en un
Carácter constante. Los caracteres delimitadores de un tipo pueden incrustarse en una cadena delimitada
por el otro, como en los ejemplos
'El dijo hola"'
"Esto contiene un '"
Alternativamente, un delimitador doble sin espacios intermedios incrustados se considera como un
Carácter único de la constante. Por ejemplo
"¿No es un buen día?"
tiene el valor ¿No es un buen día?
El número de caracteres en una cadena se llama longitud y puede ser cero. Por ejemplo, ''
y "" son constantes de caracteres de longitud cero.
Mencionamos aquí la regla particular para el formulario fuente con respecto a las constantes de caracteres
que están escritas en más de una línea (¡necesarias porque las constantes pueden incluir los caracteres!
y &): no solo cada línea que se continúa sin un comentario final, sino que cada
la línea de continuación debe comenzar con una marca de continuación. Cualquier espacio en blanco después de un final
el signo y el signo anterior no son parte de la constante, ni lo son
los símbolos de sí mismos son parte de la constante. Todo lo demás, incluidos los espacios en blanco, es parte de
el constante. Un ejemplo es
long_string =
Y
'Si estuviera con ella, la noche se publicaría demasiado pronto;
Y
& Pero ahora se agregan minutos a las horas;
Y
Y a pesar de mí ahora, cada minuto parece una luna;
Y
Y sin embargo, no para mí, ¡brille el sol para socorrer las flores!
Y
Y
Pack noche, día de pío; buen día, de noche ahora pide prestado:
Y
Y
Corto, de noche, de noche, y alargate mañana.
En cualquier computadora, los personajes tienen una propiedad conocida como secuencia de clasificación. Uno
puede hacer la pregunta de si un personaje aparece antes o después de otro en la secuencia.
Esta pregunta se plantea en una forma natural como '¿C precede a M?', Y veremos
más tarde, cómo se puede expresar esto en términos de Fortran. Fortran requiere la compilación de la computadora
secuencia para satisfacer las siguientes condiciones:
• A es menor que B es menor que C ... es menor que Y es menor que Z;
• a es menor que b es menor que c ... es menor que y es menor que z;
• 0 es menor que 1 es menor que 2 ... es menor que 8 es menor que 9;
• el blanco es menor que A y Z es menor que 0, o el blanco es menor que 0 y 9 es menor que A;
• el espacio en blanco es menor que ay z es menor que 0, o el espacio en blanco es menor que 0 y 9 es menor que a.

Página 16
18 Fortran moderno explicado
Por lo tanto, vemos que no hay una regla sobre si los números preceden o suceden
letras, ni sobre la posición de ninguno de los caracteres especiales o el guión bajo, aparte de
Regla que el blanco precede a ambas secuencias parciales. Cualquier sistema informático tiene un completo
secuencia de clasificación, y la mayoría de las computadoras hoy en día usan la secuencia de clasificación del ASCII
estándar (también conocido como ISO / IEC 646: 1991). Sin embargo, Fortran está diseñado para acomodar
otras secuencias, especialmente EBCDIC, por lo que para la portabilidad ningún programa debería depender de
cualquier pedido más allá de lo indicado anteriormente. Alternativamente, Fortran proporciona acceso al ASCII
secuencia de clasificación en cualquier computadora a través de funciones intrínsecas (Sección 9.6.1), pero este acceso
No es tan conveniente y es menos eficiente en algunas computadoras.
Se requiere un procesador para proporcionar acceso al tipo predeterminado de constante de caracteres solo
descrito. Además, puede admitir otros tipos de constantes de caracteres, en particular aquellas
de idiomas no europeos, que pueden tener más caracteres de los que se pueden proporcionar en un solo
byte. Por ejemplo, un procesador podría admitir Kanji con el valor de parámetro tipo 2; en esto
caso, se puede escribir una constante de caracteres Kanji
2_ '
'
o
kanji_ "
"
donde kanji es un entero llamado constante con el valor 2. Observamos que, en este caso, el
El parámetro tipo amable precede excepcionalmente a la constante. 4 4
No es necesario que un procesador proporcione más de un tipo de carácter, y
el estándar no requiere ninguna relación particular entre los valores de los parámetros amables
y los juegos de caracteres y la cantidad de bytes necesarios para representarlos. De hecho, todo eso
Se requiere que cada tipo de juego de caracteres incluya un carácter en blanco. Sin embargo, donde
hay otros tipos disponibles, la función intrínseca selected_char_kind, que se describe completamente en
La Sección 9.9.4 se puede usar para seleccionar un conjunto de caracteres específico.
En cuanto a los otros tipos de datos, la función kind proporciona el valor real del tipo kind
parámetro, como en
tipo ('ASCII')
Se permiten caracteres no predeterminados en los comentarios.
2.6.5 Constantes literales lógicas
El quinto tipo de constante literal es la constante literal lógica. El tipo predeterminado tiene uno
de dos valores, verdadero. y falso. . Estas constantes lógicas normalmente se usan solo para
Inicialice las variables lógicas a sus valores requeridos, como veremos en la Sección 3.6.
El tipo predeterminado tiene un valor de parámetro amable que depende del procesador. El actual
el valor está disponible como kind (.true.). En cuanto a los otros tipos intrínsecos, el parámetro kind puede
ser especificado por una constante entera después de un guión bajo, como en
.false._1
.verdadero_ largo
4 Estoes para facilitar que un compilador admita múltiples conjuntos de caracteres diferentes que ocurren dentro de un solo
archivo fuente.

Página 17
Elementos del lenguaje 19
Los tipos lógicos no predeterminados son útiles para almacenar matrices lógicas de forma compacta; diferimos más
discusión hasta la Sección 7.7.
2.6.6 Constantes binarias, octales y hexadecimales
Una constante binaria, octal o hexadecimal ('boz') se permite como una constante literal en forma limitada
circunstancias para proporcionar la secuencia de bits de un entero almacenado o valor real. Es conocido como
'boz' constante.
Una constante 'boz' puede tomar la forma de la letra b seguida de un entero binario en
apóstrofes, la letra o seguida de un entero octal en apóstrofes, o la letra z seguida
por un entero hexadecimal en apóstrofes. Ejemplos son b'1011 ', o'715' y z'a2f '. los
las letras b, o y z pueden estar en mayúsculas, al igual que los dígitos hexadecimales aa f. Un par de
se pueden usar comillas en lugar de un par de apóstrofes. En todos los casos, es un exacto
representación de una secuencia de bits. La longitud no debe exceder el tamaño de almacenamiento más grande de un
valor real o entero.
Una constante 'boz' está permitida solo en una declaración de datos (Sección 8.5.2) y como un real
argumento de un pequeño número de procedimientos intrínsecos (Capítulo 9).
Una constante binaria, octal o hexadecimal también puede aparecer en un archivo interno o externo como
una cadena de dígitos, sin la letra inicial y los delimitadores (consulte la Sección 11.3.2).
2.7 nombres
Un programa Fortran hace referencia a muchas entidades diferentes por su nombre. Dichos nombres deben consistir en
entre uno y 63 caracteres alfanuméricos - letras, guiones bajos y números - de los cuales
El primero debe ser una carta. No hay otras restricciones en los nombres; en particular hay
sin palabras reservadas en Fortran. Así vemos que los nombres válidos son, por ejemplo,
una
una cosa
x1
masa
q123
real
tiempo de vuelo
y los nombres inválidos son
1a
! El primer caracter no es alfabético
una cosa
! Contiene un espacio en blanco
signo $
! Contiene un carácter no alfanumérico
Dentro de las limitaciones de la sintaxis, es importante para la claridad del programa elegir nombres
que tienen un significado claro: estos se conocen como nombres mnemónicos. Ejemplos son día,
mes y año para que las variables almacenen la fecha del calendario.
El uso de los nombres para referirse a las constantes, ya cumplidas en la Sección 2.6.1, se describirá completamente
en la Sección 8.3.

Página 18
20 Fortran moderno explicado
2.8 Variables escalares de tipo intrínseco
Hemos visto en la sección sobre constantes literales (Sección 2.6) que existen cinco diferentes
Tipos de datos intrínsecos. Cada uno de estos tipos también puede tener variables. La forma más sencilla por la cual
una variable puede ser declarada como de un tipo particular especificando su nombre en un tipo
declaración de declaración como
entero
:: yo
real
:: una
complejo
:: actual
lógico
:: pravda
personaje :: carta
Aquí, todas las variables tienen un tipo predeterminado, y la letra tiene una longitud predeterminada, que es 1. Explícito
los requisitos también se pueden especificar a través de parámetros de tipo, como en los ejemplos
entero (tipo = 4)
:: yo
real (tipo = largo)
:: una
carácter (len = 20, kind = 1)
:: palabra inglesa
carácter (len = 20, kind = kanji) :: kanji_word
El carácter es el único tipo que tiene dos parámetros, y aquí las dos variables de caracteres
cada uno tiene una longitud 20. Cuando sea apropiado, solo se puede especificar uno de los parámetros, dejando
el otro para tomar su valor predeterminado, como en los casos
personaje (kind = kanji) :: kanji_letter
personaje (len = 20)
:: palabra inglesa
Las formas más cortas
entero (4)
:: yo
real (largo)
:: una
personaje (20, 1)
:: palabra inglesa
personaje (20, kanji) :: kanji_word
personaje (20)
:: palabra inglesa
están disponibles, pero tenga en cuenta que
personaje (kanji) :: kanji_letter
! Tener cuidado
no es una abreviatura de
personaje (kind = kanji) :: kanji_letter
porque un solo parámetro sin nombre se toma como el parámetro de longitud.
2.9 Tipos de datos derivados
Cuando se programa, a menudo es útil poder manipular objetos que son más
sofisticado que los de los tipos intrínsecos. Imagine, por ejemplo, que deseamos
especificar objetos que representan personas. Cada persona en nuestra aplicación se distingue por un
nombre, edad y número de identificación. Fortran nos permite definir un dato correspondiente
escriba de la siguiente manera:

Página 19
Elementos del lenguaje 21
tipo de persona
carácter (len = 10) :: nombre
real
:: años
entero
:: carné de identidad
persona de tipo final
Esta es la definición del tipo y se conoce como definición de tipo derivado. Un objeto escalar
de tal tipo se llama estructura. Para crear una estructura de ese tipo, escribimos un
declaración de declaración de tipo apropiada, como
tipo (persona) :: usted
La variable escalar usted es entonces un objeto compuesto de tipo persona que contiene tres
componentes, uno correspondiente al nombre, otro a la edad y un tercio a la
número de identificación.
Como se describirá en las Secciones 3.9 y 3.10, una variable como la que puede aparecer en
expresiones y asignaciones que involucran otras variables o constantes de la misma o diferente
tipos. Además, cada uno de los componentes de la variable puede ser referenciado individualmente
usando el porcentaje de caracteres del selector de componentes (%). El número de identificación de ustedes,
por ejemplo, se accede como
tu% id
y esta cantidad es una variable entera que podría aparecer en una expresión como
tu% id + 9
Del mismo modo, si hubiera un segundo objeto del mismo tipo:
tipo (persona) :: yo
las diferencias en edades podrían establecerse escribiendo
tu% de edad - yo% de edad
Se mostrará en la Sección 3.9 cómo se puede dar un significado a una expresión como
tu - yo
Así como los tipos de datos intrínsecos tienen constantes literales asociadas, también pueden hacerlo las constantes
literales.
de tipo derivado se especificará. Su forma es el nombre del tipo seguido de la constante
valores de los componentes, en orden y encerrados entre paréntesis. Por lo tanto, la constante
persona ('Smith', 23.5, 2541)
puede escribirse asumiendo el tipo derivado definido al comienzo de esta sección, y podría
ser asignado a una variable del mismo tipo:
usted = persona ('Smith', 23.5, 2541)
Cualquiera de estos constructores de estructuras puede aparecer solo después de la definición de tipo derivado.
Un tipo derivado puede tener un componente que es de un tipo derivado previamente definido. Esto es
ilustrado en la Figura 2.1. Una variable de tipo triángulo puede declararse así
tipo (triángulo) :: t

Página 20
22 Fortran moderno explicado
Figura 2.1 Un tipo derivado con un componente de un tipo derivado previamente definido.
punto de tipo
real :: x, y
punto final de tipo
tipo triángulo
tipo (punto) :: a, b, c
triángulo de tipo final
yt tiene componentes t% a, t% b, y t% c, todos de tipo punto; t% a tiene componentes t% a% x y
t% a% y de tipo real.
Se puede acceder a las partes reales e imaginarias de una variable compleja como pseudo-
componentes re y im para las partes real e imaginaria, respectivamente. Por ejemplo,
La impedancia% re y la impedancia% im son las partes reales e imaginarias de la variable compleja.
impedancia. También son accesibles, más inconvenientemente, por las funciones intrínsecas reales
y aimag (Sección 9.3.1).
2.10 Matrices de tipo intrínseco
Otro objeto compuesto compatible con Fortran es la matriz. Una matriz consta de un
conjunto rectangular de elementos, todos del mismo tipo y parámetros de tipo. Hay una serie de
formas en que se pueden declarar las matrices; por el momento consideraremos solo la declaración
de matrices de tamaños fijos. Para declarar una matriz denominada a de diez elementos reales, agregamos el
atributo de dimensión a la declaración de declaración de tipo por lo tanto:
real, dimensión (10) :: a
Los elementos sucesivos de toda la matriz a son a (1), a (2), a (3), ..., a (10). El número
de elementos de una matriz se llama su tamaño. Cada elemento de la matriz es un escalar.
Muchos problemas requieren una declaración más elaborada que una en la que el primer elemento es
designado 1, y es posible en Fortran declarar un límite inferior y superior:
real, dimensión (-10: 5) :: vector
Este es un vector de 16 elementos, vector (-10), vector (-9), ..., vector (5). Así vemos
que mientras que siempre necesitamos especificar el límite superior, el límite inferior es opcional, y por
el valor predeterminado tiene el valor 1.
Una matriz puede extenderse en más de una dimensión, y Fortran permite hasta 15 dimensiones
a especificar 5 Por ejemplo,
real, dimensión (5,4) :: b
declara una matriz con dos dimensiones, y
real, dimensión (-10: 5, -20: -1, 0:15, -15: 0, 16, 16, 16) :: cuadrícula
5 Si una matriz también es una matriz (Capítulo 17), el límite se aplica a la suma del rango y la clase.

Página 21
Elementos del lenguaje 23
declara siete dimensiones, las cuatro primeras con límites inferiores explícitos. Puede verse que el
tamaño de esta segunda matriz es
16 × 20 × 16 × 16 × 16 × 16 × 16 = 335 544 320,
y que las matrices de muchas dimensiones pueden colocar grandes demandas en la memoria de un
computadora: una matriz
real, dimensión (10, 10, 10, 10, 10, 10, 10, 10, 10, 10) :: x
de enteros de cuatro bytes requiere 40 GB de memoria. El número de dimensiones de una matriz es
conocido como su rango. Por lo tanto, la cuadrícula tiene un rango de siete. Se considera que los escalares tienen rango
cero. El número de elementos a lo largo de una dimensión de una matriz se conoce como la extensión en ese
dimensión. Por lo tanto, la cuadrícula tiene extensiones 16, 20,. . . .
La secuencia de extensiones se conoce como la forma. Por ejemplo, la cuadrícula tiene la forma
(16,20,16,16,16,16,16).
Un tipo derivado puede contener un componente de matriz. Por ejemplo, el siguiente tipo
tipo triplete
real
:: u
real, dimensión (3)
:: du
real, dimensión (3,3) :: d2u
triplete de tipo final
podría usarse para mantener el valor de una variable en tres dimensiones y los valores de su primera
y segundas derivadas. Si t es de tipo triplete, t% du y t% d2u son matrices de tipo real.
Figura 2.2 El orden de los elementos en la matriz b (5,4).
Algunas declaraciones tratan los elementos de una matriz uno por uno en un orden especial que llamamos
El orden del elemento de la matriz. Se obtiene contando más rápidamente en las primeras dimensiones.
Por lo tanto, los elementos de la cuadrícula en orden de elemento de matriz son
b (1,1)
b (2,1)
b (3,1)
b (4,1)
b (5,1)
b (1,2)
b (2,2)
b (3,2)
b (4,2)
b (5,2)
b (1,3)
b (2,3)
b (3,3)
b (4,3)
b (5,3)
b (1,4)
b (2,4)
b (3,4)
b (4,4)
b (5,4)

Página 22
24 Fortran moderno explicado
cuadrícula (-10, -20, 0, -15, 1, 1, 1)
cuadrícula (-9, -20, 0, -15, 1, 1, 1)
...
cuadrícula (5, -1, 15, 0, 16, 16, 16)
Esto se ilustra para una matriz de dos dimensiones en la Figura 2.2. La mayoría de las implementaciones
en realidad almacenar matrices en almacenamiento contiguo en orden de elementos de matriz, pero enfatizamos que
El estándar no requiere esto.
Hacemos referencia a un elemento individual de una matriz especificando, como en los ejemplos anteriores,
sus valores de subíndice. En los ejemplos usamos constantes enteras, pero en general cada subíndice
puede estar formado por una expresión entera escalar, es decir, cualquier expresión aritmética cuyo valor
es escalar y de tipo entero. Cada subíndice debe estar dentro de los rangos correspondientes definidos
en la declaración de matriz y el número de subíndices debe ser igual al rango. Ejemplos son
a (1)
a (i * j)
! i y j son de tipo entero
a (nint (x + 3.))
! x es de tipo real
t% d2u (i + 1, j + 2)
! t es de tipo derivado triplete
donde nint es una función intrínseca para convertir un valor real al entero más cercano (ver
Sección 9.3.1). Además, se puede hacer referencia a las submatrices, llamadas secciones, especificando un
rango para uno o más subíndices. Los siguientes son ejemplos de secciones de matriz:
a (i: j)
! Rango de rango uno de tamaño j-i + 1
b (k, 1: n)
! Rango uno de tamaño n
c (1: i, 1: j, k)
! Matriz de rango dos con extensiones i y j
Describimos las secciones de matriz con más detalle en la Sección 7.12. Una sección de matriz es en sí misma
array, pero no se debe acceder a sus elementos individuales a través del designador de sección. Así,
b (k, 1: n) (l) no se puede escribir; debe expresarse como b (k, l).
Una forma adicional de subíndice se muestra en
a (punto)
! ipoint es una matriz entera de rango uno
donde ipoint es una matriz de índices de rango uno, que apunta a elementos de la matriz. Por lo tanto, puede ser
visto que a (ipoint), que identifica tantos elementos de a como ipoint tiene elementos, es un
ejemplo de otro objeto con valor de matriz, y ipoint se conoce como subíndice vectorial.
Esto se cumplirá con mayor detalle en la Sección 7.12.
A menudo es conveniente poder definir una constante de matriz. En Fortran, una matriz de rango uno puede
ser construido como una lista de elementos encerrados entre los tokens (/ y /) o los caracteres
[y], respectivamente. Un ejemplo simple es
(/ 1, 2, 3, 5, 10 /)
que es un conjunto de rango uno y tamaño cinco. Para obtener una serie de valores, los valores individuales
puede definirse por una expresión que depende de una variable entera que tenga valores en un rango,
Con una zancada opcional. Así, el constructor
[1, 2, 3, 4, 5]
Se puede escribir como

Página 23
Elementos del lenguaje 25
[(i, i = 1,5)]
y
(/ 2, 4, 6, 8 /)
como
(/ (i, i = 2,8,2) /)
y
(/ 1.1, 1.2, 1.3, 1.4, 1.5 /)
como
(/ (i * 0.1, i = 11,15) /)
Una constante de matriz de rango superior a uno puede construirse utilizando la función remodelar
(consulte la Sección 9.15.3) para remodelar una constante de matriz de rango uno.
Una descripción completa de los constructores de matrices está reservada para la Sección 7.16.
2.10.1 Declarar entidades de diferentes formas
Para declarar varias entidades del mismo tipo pero con formas diferentes, Fortran permite
la conveniencia de usar una sola declaración. Si hay o no un atributo de dimensión
presente, las matrices se pueden declarar colocando la información de la forma después del nombre de la matriz:
entero :: a, b, c (10), d (10), e (8, 7)
Si el atributo de dimensión está presente, proporciona una forma predeterminada para las entidades que no son
seguido de su propia información de forma, y se ignora para aquellos que son:
entero, dimensión (10) :: c, d, e (8, 7)
2.10.2 Objetos asignables
A veces se requiere que un objeto sea de un tamaño que se conoce solo después de que algunos datos han sido
leer o algunos cálculos realizados. Esto se puede implementar mediante el uso de punteros (ver
Sección 2.12), pero existen ventajas significativas para la gestión y ejecución de la memoria.
velocidad en el uso de objetos asignables cuando no se necesita la funcionalidad adicional de los punteros.
Por lo tanto, para este propósito más restringido, una matriz puede recibir el atributo asignable
por una declaración como
real, dimensión (:, :), asignable :: a
Tal matriz se llama asignable. Su rango se especifica cuando se declara, pero los límites
no están definidos hasta que una instrucción de asignación como
asignar (a (n, 0: n + 1))
! n es de tipo entero y está definido
ha sido ejecutado por ello.
El estado de asignación de un objeto asignable es asignado o no asignado. Es inicial
el estado no está asignado y se asigna después de la ejecución exitosa de una asignación
declaración. El objeto está disponible durante la ejecución del programa.
Cuando un objeto asignable como a ya no es necesario, puede ser desasignado por ejecución
de la declaración

Página 24
26 Fortran moderno explicado
desasignar (a)
después de lo cual el objeto no está asignado.
Esta importante característica se describe completamente en el Capítulo 6.
2.11 Subcadenas de caracteres
Es posible construir matrices de caracteres, al igual que es posible construir matrices de cualquier otro
tipo:
personaje, dimensión (80) :: línea
declara una matriz, llamada línea, de 80 elementos, cada uno de ellos de longitud. Cada personaje
puede abordarse mediante la referencia habitual, por ejemplo, la línea (i). En este caso, sin embargo, un más
declaración apropiada podría ser
carácter (len = 80) :: línea
que declara un objeto de datos escalares de 80 caracteres. Estos pueden ser referenciados individualmente o
en grupos que usan una notación de subcadena
línea (i: j)
! i y j son de tipo entero
que hace referencia a todos los caracteres de i a j en línea. El colon se usa para separar los dos
subíndices de subcadena, que pueden ser expresiones enteras escalares. El colon es obligatorio.
en referencias de subcadena, de modo que hacer referencia a un solo carácter requiere una línea (i: i). Existen
valores predeterminados para los subíndices de subcadena. Si se omite el inferior, se supone el valor 1;
si se omite el superior, se supone un valor correspondiente a la longitud del carácter. Así,
la línea (: i) es equivalente a la línea (1: i)
line (i :) es equivalente a line (i: 80)
line (:) es equivalente a line o line (1:80)
Si i es mayor que j en la línea (i: j), el valor es una cadena de tamaño cero.
Ahora podemos combinar la declaración de longitud con la declaración de matriz para construir matrices de
objetos de caracteres de longitud especificada, como en
carácter (len = 80), dimensión (60) :: página
que podría usarse para definir el almacenamiento de los caracteres de una página completa, con 60 elementos
de una matriz, cada uno de longitud 80. Para hacer referencia a la línea j en una página, podemos escribir la página (j),
y para hacer referencia al carácter i en esa línea, podríamos combinar el subíndice de matriz y el carácter
anotaciones de subcadena en
página (j) (i: i)
También se puede formar una subcadena de una constante de carácter o de un componente de estructura:
«ABCDEFGHIJKLMNOPQRSTUVWXYZ» (j: j)
tu% nombre (1: 2)
En esta sección hemos utilizado variables de caracteres con una longitud máxima declarada. Esta
es adecuado para la mayoría de las aplicaciones de manipulación de personajes, pero se puede evitar la limitación
con variables asignables, como se describe en la Sección 15.4.2.

Página 25
Elementos del lenguaje 27
2.12 Punteros
En el lenguaje cotidiano, los sustantivos a menudo se usan de una manera que hace que su significado solo sea preciso
por el contexto 'El presidente dijo que ...' será entendido precisamente por el
lector que sabe que el contexto es el Comité Fortran que desarrolla Fortran 90 y que
su presidente era entonces Jeanne Adams.
Del mismo modo, en un programa de computadora puede ser muy útil poder usar un nombre que
Se puede hacer referencia a diferentes objetos durante la ejecución del programa. Un ejemplo
es la multiplicación de un vector por una secuencia de matrices cuadradas. Podríamos escribir código que
calcula
yi=
norte


j=1
a ij x j, i = 1,2, ..., n
del vector x j , j = 1,2, ..., n. Para usar esto para calcular
BCz
primero podríamos hacer que x se refiera a z y A se refiera a C, usando así nuestro código para calcular y = Cz,
luego haga que x se refiera a y y A se refiera a B para que nuestro código calcule el vector de resultados que finalmente
querer.
Un objeto que se puede hacer para referirse a otros objetos de esta manera se llama puntero, y
debe declararse con el atributo puntero, por ejemplo
real, puntero
:: hijo
real, puntero, dimensión (:)
:: x, y
real, puntero, dimensión (:, :) :: a
En el caso de una matriz, solo se declara el rango (número de dimensiones) y los límites (y
por lo tanto, la forma) se toman de la del objeto al que apunta. Dado tal puntero de matriz
declaración, el compilador organiza el almacenamiento de un descriptor que luego contendrá la dirección de
el objeto real (conocido como el objetivo) y contiene, si es una matriz, sus límites y zancadas.
Además de apuntar a variables existentes, se puede hacer un puntero explícitamente para apuntar a nada:
anular (hijo, x, y, a)
(la anulación se describe en la Sección 3.14) o se le puede dar almacenamiento fresco por medio de una asignación
declaración como
asignar (hijo, x (10), y (-10: 10), a (n, n))
En el caso de las matrices, los límites inferior y superior se especifican igual que para la dimensión
atributo (Sección 2.10), excepto que se permite cualquier expresión entera escalar. Este uso
de punteros proporciona un medio para acceder al almacenamiento dinámico pero, como se ve en la Sección 2.10.2 y
descrito más adelante en el Capítulo 6, las matrices asignables proporcionan una mejor manera de hacerlo en los casos
donde la propiedad 'apuntando' no es esencial.
Por defecto, los punteros están inicialmente indefinidos (ver también el párrafo final de la Sección 3.3).
Este es un estado muy indeseable ya que no hay forma de probarlo. Sin embargo, puede ser
evitado mediante el uso de la declaración:
real, puntero :: hijo => nulo ()28 Fortran moderno explicado

(la función nulo se describe en la Sección 9.17) y recomendamos que esto siempre sea
empleado. Alternativamente, los punteros pueden definirse tan pronto como entren en alcance por
ejecución de una declaración nula o una asignación de puntero.
Los componentes de tipos derivados pueden tener el atributo puntero. Esto permite un
aplicación principal de punteros: la construcción de listas vinculadas. Como un simple ejemplo, nosotros
podría decidir mantener un vector disperso como una cadena de variables del tipo que se muestra en la Figura 2.3,
lo que nos permite acceder a las entradas una por una; dado
tipo (entrada), puntero :: cadena
donde chain es un escalar de este tipo y contiene una cadena de longitud dos, sus entradas
son chain% index y chain% next% index, y chain% next% next habrá sido anulado.
Se pueden crear entradas adicionales cuando sea necesario mediante una instrucción de asignación apropiada. Nosotros
diferir los detalles a la Sección 3.13.
Figura 2.3 Un tipo para mantener un vector disperso como una cadena de variables.
tipo de entrada
real
:: valor
entero
:: índice
tipo (entrada), puntero :: siguiente
entrada de tipo final
Cuando un puntero es de tipo derivado y se selecciona un componente como el índice de% de cadena, es
en realidad un componente del objetivo del puntero que está seleccionado.
Un subobjeto no es un puntero a menos que tenga un selector de componentes final para el nombre de un
componente puntero, por ejemplo, cadena% siguiente (mientras que cadena% valor yx (1) no lo son).
Los punteros se discutirán en detalle en capítulos posteriores (especialmente las Secciones 3.13, 5.7.2, 7.13,
7.14, 8.5.3, 8.5.4 y 9.2).
2.13 Objetos y subobjetos
Hemos visto que los tipos derivados pueden tener componentes que son matrices, como en
tipo triplete
real, dimensión (3) :: vértice
triplete de tipo final
y las matrices pueden ser de tipo derivado como en el ejemplo
tipo (triplete), dimensión (10) :: t
Una estructura única (por ejemplo, t (2)) siempre se considera escalar, pero puede tener un
componente (por ejemplo, t (2)% vértice) que es una matriz. Los tipos derivados pueden tener componentes
de otros tipos derivados. El término componente último se usa para un subobjeto obtenido por
calificación repetida hasta que no haya más componentes o lleguemos a una asignación o
componente puntero.
Un objeto referenciado por un nombre no calificado (todos los caracteres alfanuméricos) se denomina
objeto nombrado y no es parte de un objeto más grande. Sus subobjetos tienen designadores que consisten

Página 2
Elementos del lenguaje 29
del nombre del objeto base seguido de uno o más calificadores (por ejemplo, t (1: 7) y
t (1)% vértice). Cada calificador sucesivo especifica una parte del objeto base especificado por
nombre o designador que lo precede.
Observamos que el término matriz se usa para cualquier objeto que no sea escalar, incluida una matriz
sección o un componente con valor de matriz de una estructura. El término variable se usa para cualquier nombre
objeto que no se especifica como una constante y para cualquier parte de dicho objeto, incluida la matriz
elementos, secciones de matriz, componentes de estructura y subcadenas.
2.14 Resumen
En este capítulo hemos introducido los elementos del lenguaje Fortran. El conjunto de caracteres tiene
enumerado, y la manera en que las secuencias de caracteres forman constantes y nombres literales
explicado. En este contexto, hemos encontrado los cinco tipos de datos intrínsecos definidos en Fortran,
y visto cómo cada tipo de datos tiene constantes literales correspondientes y objetos con nombre. Tenemos
visto cómo se pueden construir tipos derivados a partir de los tipos intrínsecos. Hemos introducido uno
método por el cual se pueden declarar matrices y se ve cómo sus elementos pueden ser referenciados por
expresiones de subíndice Los conceptos de la sección de matriz, la subcadena de caracteres y el puntero tienen
se han presentado, se han introducido matrices asignables y se han definido algunos términos importantes.
En el siguiente capítulo veremos cómo se pueden combinar estos elementos en expresiones
y declaraciones, equivalentes de Fortran de 'frases' y 'oraciones'.
Ejercicios
1. Para cada una de las siguientes afirmaciones, indique si es verdadero, falso o no determinado, de acuerdo con
las secuencias de clasificación de Fortran:
b es menor que m
8 es menos que 2
* es mayor que T
$ es menor que /
el espacio en blanco es mayor que A
en blanco es menos de 6
2. ¿Cuál de las líneas de Fortran en el código
x=y
3 a = b + c! añadir
palabra = 'cadena'
a = 1.0; b = 2.0
a = 15.! inicializar a; b = 22.! y B
song = "La vida es justa y
y un tazón de cerezas "
chide = 'No desperdicio,
¡No quiero!'
0 c (3: 4) = 'arriba "
están escritos correctamente de acuerdo con los requisitos del formulario fuente de Fortran? Cuales contienen
¿comentario? ¿Qué líneas son líneas iniciales y cuáles son líneas de continuación?

Página 3
30 Fortran moderno explicado
3. Clasifique las siguientes constantes literales de acuerdo con los cinco tipos de datos intrínsecos de Fortran. Cual
no son constantes literales legales?
-43
'palabra'
4.39
1.9-4
0.0001e + 20
'cosas y tonterías'
49
(0., 1.)
(1.e3,2)
'No puedo'
«(4.3e9, 6.2)»
.true._1
e5
'no' 't'
1_2
"OKAY"
z10
z'10 '
4. ¿Cuáles de los siguientes nombres son nombres legales de Fortran?
nombre
nombre32
cociente
123
a182c3
no vayas
¡detener!
quemar_
no vayas
nombre largo
5. ¿Cuáles son los elementos primero, décimo, undécimo y último de las siguientes matrices?
real, dimensión (11)
:: una
real, dimensión (0:11)
:: b
real, dimensión (-11: 0)
:: C
real, dimensión (10,10)
:: d
real, dimensión (5,9)
:: e
dimensión real (5,0: 1,4) :: f
Escriba un constructor de matriz de once elementos enteros.
6. Dada la declaración de matriz
carácter (len = 10), dimensión (0: 5,3) :: c
¿Cuál de los siguientes designadores de subobjetos es legal?
c (2,3)
c (4: 3) (2,1)
c (6,2)
c (5,3) (9: 9)
c (0,3)
c (2,1) (4: 8)
c (4,3) (:)
c (3,2) (0: 9)
c (5) (2: 3)
c (5: 6)
c (5,3) (9)
C(,)
7. Escriba definiciones de tipo derivado apropiadas para:
i) un registro de vehículo;
ii) un círculo;
iii) un libro (título, autor y número de páginas).
Dé un ejemplo de un tipo derivado constante para cada uno.
8. Dada la declaración para t en la Sección 2.13, ¿cuáles de los siguientes objetos y subobjetos son
matrices?
t
t (4)% de vértice (1)
t (10)
t (5: 6)
t (1)% de vértice
t (5: 5)

Página 4
Elementos del lenguaje 31
9. Escriba especificaciones para estas entidades:
a) una variable entera dentro del rango -10 20 a 10 20 ;
b) una variable real con un mínimo de 12 dígitos decimales de precisión y un rango de 10 -100 a
10 100 ;
c) una variable de caracteres Kanji en un procesador que admite Kanji con kind = 2.

Página 5

Página 6

3. Expresiones y asignaciones
3.1 Introducción
Hemos visto en el capítulo anterior cómo podemos construir las 'palabras' de Fortran: el
constantes, palabras clave y nombres: de los elementos básicos del conjunto de caracteres. En este capítulo
descubriremos cómo estas entidades pueden combinarse más en 'frases' o expresiones,
y cómo estos, a su vez, pueden combinarse en 'oraciones' o declaraciones.
En una expresión, describimos un cálculo que debe realizar la computadora. los
El resultado del cálculo se puede asignar a una variable. Una secuencia de tareas
es la forma en que especificamos, paso a paso, la serie de cálculos individuales a ser
llevado a cabo para llegar al resultado deseado. Hay conjuntos separados de reglas para
expresiones y asignaciones, dependiendo de si los operandos en cuestión son numéricos,
lógico, de carácter o derivado en tipo, y si son escalares o matrices. También hay
reglas separadas para asignaciones de puntero. Discutiremos cada conjunto de reglas a su vez, incluyendo un
Descripción de las expresiones relacionales que producen un resultado de tipo lógico y son necesarias
en declaraciones de control (ver el siguiente capítulo). Para simplificar la discusión inicial, comenzamos
al considerar expresiones y tareas que están intrínsecamente definidas y que no involucran
matrices ni entidades de tipos de datos derivados.
Una expresión en Fortran está formada por operandos y operadores, combinados de una manera que
sigue las reglas de la sintaxis de Fortran. Una expresión simple que implica una diádica (o binaria)
el operador tiene la forma
operador de operando operando
un ejemplo siendo
x+y
y un operador unario o monádico tiene la forma
operador operando
un ejemplo siendo
-y
El tipo y tipo del resultado están determinados por el tipo y tipo de los operandos y
no dependen de sus valores. Los operandos pueden ser constantes, variables o funciones (ver
Capítulo 5), y una expresión puede ser utilizada como un operando. De esta manera podemos construir
expresiones más complicadas como
operador de operando operador de operando operando
Fortran moderno explicado, 2da edición. Michael Metcalf, John Reid y Malcolm Cohen. prensa de la Universidad de Oxford
(2018) cG Michael Metcalf, John Reid y Malcolm Cohen 2018. DOI 10.1093 / oso / 9780198811893.001.0001

Página 7
34 Fortran moderno explicado
donde los operandos consecutivos están separados por un solo operador. Cada operando debe tener un
valor definido
Las reglas de Fortran establecen que se evalúan las partes de las expresiones sin paréntesis
sucesivamente de izquierda a derecha para operadores de igual precedencia, con la excepción de **
(exponenciación, ver Sección 3.2). Si es necesario evaluar una parte de una expresión,
o subexpresión, antes de otra, se pueden usar paréntesis para indicar qué subexpresión
debe ser evaluado primero. En
operador de operando (operador de operando operando)
se evaluará la subexpresión entre paréntesis y el resultado se utilizará como un operando para
primer operador
Si una expresión o subexpresión no tiene paréntesis, el procesador puede evaluar
una expresión equivalente; es decir, una expresión que siempre tiene el mismo valor aparte, posiblemente,
de los efectos del redondeo numérico. Por ejemplo, si a, byc son variables reales, el
expresión
aBC
podría ser evaluado como
a B C)
en un procesador que puede multiplicarse mucho más rápido de lo que puede dividirse. Por lo general, tales cambios
son bienvenidos al programador ya que el programa se ejecuta más rápido, pero cuando no lo son (por
ejemplo, porque darían lugar a más redondeos) los paréntesis deben insertarse porque
Se requiere que el procesador los respete.
Si dos operadores se siguen inmediatamente, como en
operador de operador operador de operando
La única interpretación posible es que el segundo operador es unario. Por lo tanto, hay un general
Regla que un operador binario no debe seguir inmediatamente después de otro operador.
3.2 Expresiones numéricas escalares
Una expresión numérica es una expresión cuyos operandos son uno de los tres tipos numéricos:
entero, real y complejo, y cuyos operadores son
** **
exponenciación
* / multiplicación, división
+ - suma, resta
Estos operadores se conocen como operadores intrínsecos numéricos y se enumeran aquí en su orden
de precedencia. En ausencia de paréntesis, las exponenciaciones se llevarán a cabo antes
multiplicaciones y divisiones, y estas antes de sumas y restas.
Observamos que el signo menos (-) y el signo más (+) se pueden usar como operadores unarios, como en
-impuesto
Debido a que no está permitido en la notación matemática ordinaria, un signo unario menos o más no debe
siga inmediatamente después de otro operador. Cuando esto es necesario, como para x -y , los paréntesis deben
colocarse alrededor del operador y su operando:

Página 8
Expresiones y tareas 35
x ** (- y)
El parámetro type y kind type del resultado de una operación unaria son los del operando.
La excepción a la regla de izquierda a derecha señalada en la Sección 3.1 se refiere a exponenciaciones.
Mientras que la expresión
-a + b + c
será evaluado de izquierda a derecha como
((-a) + b) + c
la expresion
aBC
será evaluado como
a B C)
Para datos enteros, el resultado de cualquier división se truncará hacia cero, es decir, al
valor entero cuya magnitud es igual o menor que la magnitud del resultado exacto.
Por lo tanto, el resultado de
6/3 es
2
8/3 es
2
-8/3 es -2
Este hecho siempre debe tenerse en cuenta cuando se escriben divisiones enteras. Del mismo modo, el
resultado de
2 ** 3 es 8
mientras que el resultado de
2 ** (- 3) es 1 / (2 ** 3)
que es cero
Las reglas de Fortran permiten que una expresión numérica contenga operandos numéricos de diferentes
tipos o parámetros de tipo amable. Esto se conoce como una expresión de modo mixto. Excepto cuando
elevar un valor real o complejo a una potencia entera, el objeto del más débil (o más simple) de
los dos tipos de datos se convertirán, o se coaccionarán, en el tipo del más fuerte. El resultado
también será el del tipo más fuerte. Si, por ejemplo, escribimos
ai
cuando a es de tipo real e i es de tipo entero, entonces me convertiré a un tipo de datos real
antes de que se realice la multiplicación, y el resultado del cálculo también será de tipo
real. Las reglas se resumen para cada combinación posible para las operaciones +, -, * y
/ en la Tabla 3.1, y para la operación ** en la Tabla 3.2. Las funciones reales y cmplx que tienen
las referencias se definen en la Sección 9.3.1. En ambas tablas, significa entero, R para real y C
para complejo
Si ambos operandos son de tipo entero, el parámetro de tipo amable del resultado es el de
operando con el mayor rango de exponente decimal, o depende del procesador si los tipos difieren

Página 9
36 Fortran moderno explicado
Tabla 3.1. Tipo de resultado de un .op. b, donde .op. es +, -, * o /.
Tipo Tipo Valor de
Valor de
Tipo de
de un
de B
un usado
b usado
resultado
yo
yo
una
si
yo
yo
R
real (a, tipo (b))
si
R
yo
C
cmplx (a, 0, tipo (b)) b
C
R
yo
una
real (b, tipo (a))
R
R
R
una
si
R
R
C
cmplx (a, 0, tipo (b)) b
C
C
yo
una
cmplx (b, 0, tipo (a))
C
C
R
una
cmplx (b, 0, tipo (a))
C
C
C
una
si
C
Tabla 3.2. Tipo de resultado de a ** b.
Tipo Tipo Valor de
Valor de
Tipo de
de un
de B
un usado
b usado
resultado
yo
yo
una
si
yo
yo
R
real (a, tipo (b))
si
R
yo
C
cmplx (a, 0, tipo (b)) b
C
R
yo
una
si
R
R
R
una
si
R
R
C
cmplx (a, 0, tipo (b)) b
C
C
yo
una
si
C
C
R
una
cmplx (b, 0, tipo (a))
C
C
C
una
si
C
pero los rangos de exponente decimal son los mismos. Si ambos operandos son de tipo real o complejo,
el parámetro tipo amable del resultado es el del operando con la mayor precisión decimal,
o depende del procesador si los tipos difieren pero las precisiones decimales son las mismas. Si uno
el operando es de tipo entero y el otro es real o complejo, el parámetro de tipo del resultado es
la del operando real o complejo.
Tenga en cuenta que una constante literal en una expresión de modo mixto se mantiene con su propia precisión, que
puede ser menor que el de la expresión. Por ejemplo, dada una variable de tipo largo
(Sección 2.6.2), el resultado de a / 1.7 será menos preciso que el de a / 1.7_long.
En el caso de elevar un valor complejo a una potencia compleja, se toma el valor principal 1 .
No está permitido elevar un valor real negativo a una potencia real ya que el resultado exacto probablemente
tiene una parte imaginaria distinta de cero.
1 El valor principal de a b es exp (b (log | a | + iarga)), con −π <arga ≤ π.

Página 10
Expresiones y tareas 37
3.3 Variables definidas e indefinidas
En el curso de las explicaciones en este y los siguientes capítulos, a menudo nos referiremos a un
variable que se define o no se define. En el capítulo anterior, mostramos cómo un escalar
variable puede ser llamada a la existencia por una declaración como
real :: velocidad
En este caso simple, la velocidad variable tiene, al comienzo de la ejecución del programa,
sin valor definido Es indefinido No debe hacerse ningún intento de hacer referencia a su valor ya que tiene
ninguna. Una forma común en la que podría definirse es que se le asigne un valor:
velocidad = 2.997
Después de la ejecución de dicha declaración de asignación, tiene un valor, y ese valor puede ser
referenciado, por ejemplo en una expresión:
velocidad * 0.5
Para un objeto compuesto, todos sus subobjetos que no son punteros deben ser individualmente
definido antes del objeto como un todo se considera como definido. Por lo tanto, se dice que una matriz es
definido solo cuando se define cada uno de sus elementos, se define un objeto de un tipo de datos derivado
solo cuando se define cada uno de sus componentes sin puntero y se define una variable de caracteres
solo cuando se define cada uno de sus caracteres.
Una variable que se define no necesariamente conserva su estado de definición en todo el
ejecución de un programa. Como veremos en el Capítulo 5, una variable que es local para un solo
el subprograma generalmente se vuelve indefinido cuando el control se devuelve desde ese subprograma. En
En ciertas circunstancias, incluso es posible que un solo elemento de matriz se vuelva indefinido y
esto hace que la matriz considerada como un todo se vuelva indefinida; una regla similar es válida para
entidades de tipo de datos derivados y para variables de caracteres.
Los medios para especificar el valor inicial de una variable se explican en la Sección 8.5.
En el caso de un puntero, el estado de asociación del puntero puede estar indefinido o definido por
estar asociado con un objetivo o estar desasociado, lo que significa que no está asociado
con un objetivo pero tiene un estado definido que puede ser probado por la función asociada
(Sección 9.2). Aunque un puntero esté asociado con un objetivo, el objetivo en sí puede ser
definido o indefinido. Se proporcionan los medios para especificar el estado inicial de disociado (ver
Sección 8.5.3).
3.4 Asignación numérica escalar
La forma general de una asignación numérica escalar es
variable = expr
donde variable es una variable numérica escalar y expr es una expresión numérica escalar. Si expr
no es del mismo tipo o tipo que la variable, se convertirá a ese tipo y tipo antes
la asignación se lleva a cabo de acuerdo con el conjunto de reglas que figuran en la Tabla 3.3 (las funciones
int, real y cmplx se definen en la Sección 9.3.1).
Notamos que si el tipo de variable es entero pero expr no lo es, entonces la asignación resultará
en una pérdida de precisión a menos que expr tenga un valor integral. Del mismo modo, asignar un real

Página 11
38 Fortran moderno explicado
Tabla 3.3. Conversión numérica para la instrucción de asignación variable = expr.
Tipo de variable Valor asignado
entero
int (expr, kind (variable))
real
real (expr, kind (variable))
complejo
cmplx (expr, kind = kind (variable))
la expresión a una variable real de un tipo con menos precisión también causará una pérdida de precisión a
ocurrir, y la asignación de una cantidad compleja a una variable no compleja implica la pérdida
de la parte imaginaria. Por lo tanto, los valores en i y a siguiendo las asignaciones
i = 7.3
! i de tipo entero predeterminado
a = (4.01935, 2.12372)
! una de tipo real por defecto
son 7 y 4.01935, respectivamente. Además, si se asigna una constante literal a una variable de mayor
precisión, el resultado tendrá la precisión de la constante. Por ejemplo, dada una variable a
de tipo largo (Sección 2.6.2), el resultado de
a = 1.7
será menos preciso que el de
a = 1.7_long
3.5 Operadores relacionales escalares
Es posible en Fortran probar si el valor de una expresión numérica tiene un cierto
relación con la de otro, y de manera similar para las expresiones de caracteres. Los operadores relacionales
son
<
menos que
<=
menor o igual
==
igual
/=
no es igual
>
mas grande que
>=
mayor que o igual
Si una o ambas expresiones son complejas, solo están disponibles los operadores == y / =.
El resultado de tal comparación es uno de los valores lógicos predeterminados .true. o falso.,
y veremos en el próximo capítulo cómo tales pruebas son importantes para controlar la ejecución
de un programa. Ejemplos de expresiones relacionales (para i y j de tipo entero, a y b de tipo
real y char1 de tipo carácter predeterminado) son
i <0
expresión relacional entera
a <b
expresión relacional real
a + b> ij
expresión relacional de modo mixto
char1 == expresión relacional de caracteres 'Z'

Pagina 12
Expresiones y tareas 39
En la tercera expresión anterior, observamos que los dos componentes son de diferente valor numérico.
tipos. En este caso, y siempre que uno o los dos componentes constan de números
expresiones, las reglas establecen que los componentes deben evaluarse por separado y convertirse
al tipo y tipo de su suma antes de hacer la comparación. Por lo tanto, una expresión relacional
como
a + b <= ij
será evaluado convirtiendo el resultado de (ij) a type real.
Para las comparaciones de caracteres, los tipos deben ser los mismos y las letras se comparan de
a la izquierda hasta que se encuentre una diferencia o se descubra que las cadenas son idénticas. El resultado de la
la comparación está determinada por las posiciones en la secuencia de clasificación (ver Sección 2.6.4) de
Los primeros personajes diferentes. Si las longitudes difieren, la más corta se considera acolchada.
con espacios en blanco 2 a la derecha. Dos cadenas de tamaño cero se consideran idénticas. El efecto es
en cuanto al orden de las palabras en un diccionario. Por ejemplo, la relación 'ab' <'as' es verdadera.
Ninguna otra forma de operador relacional de modo mixto está intrínsecamente disponible, aunque tal
se puede definir un operador (Sección 3.9). Los operadores numéricos tienen prioridad sobre el
operadores relacionales.
3.6 Expresiones lógicas escalares y asignaciones
Las constantes lógicas, las variables y las funciones pueden aparecer como operandos en expresiones lógicas.
Los operadores lógicos, en orden de precedencia decreciente, son:
operador unario:
.no. negación lógica
operadores binarios:
.y.
intersección lógica
.o.
unión lógica
.eqv. y .neqv. equivalencia lógica y no equivalencia
Si asumimos una declaración lógica de la forma
lógico :: i, j, k, l
entonces las siguientes son expresiones lógicas válidas:
.not.j
j. y. k
i .o. l. y. .not.j
(.not.k .and. j .neqv. .not.l) .o. yo
En la primera expresión notamos el uso de .not. como operador unario. En la tercera expresión,
las reglas de precedencia implican que se evaluará la subexpresión l.and..not.j
primero, y el resultado combinado con i. En la última expresión, las dos subexpresiones
2 Aquí y en otros lugares, el carácter de relleno en blanco utilizado para un tipo no predeterminado depende del procesador.

Página 13
40 Fortran moderno explicado
.not.k.and.j y .not.l serán evaluados y comparados por no equivalencia. El resultado
de la comparación, verdadero. o .false., se combinará con i.
El parámetro tipo amable del resultado es el del operando para .not., Y para los demás es
el de los operandos si tienen el mismo tipo o el procesador depende de lo contrario.
Notamos que el .or. operador es un operador inclusivo; el .neqv. el operador proporciona un
lógico exclusivo o (a.and..not.b .or. .not.a.and.b).
El resultado de cualquier expresión lógica es el valor verdadero o falso, y este valor puede ser
asignado a una variable lógica como el elemento 3 del indicador de matriz lógica en el ejemplo
flag (3) = (.not. k .eqv. l) .or. j
Los valores de parámetros de tipo amable de la variable y la expresión no necesitan ser idénticos.
Una variable lógica se puede establecer en un valor predeterminado mediante una declaración de asignación:
bandera (1) = .verdadero.
bandera (2) = .false.
En los ejemplos anteriores, todos los operandos y resultados fueron de tipo lógico; ningún otro dato
type puede participar en una operación o asignación lógica intrínseca.
Los resultados de varias expresiones relacionales pueden combinarse en una expresión lógica,
y asignado, como en
real
:: a, b, x, y
lógico :: cond
...
cond = a> b. o. x <0.0. y. y> 1.0
donde notamos la precedencia de los operadores relacionales sobre los operadores lógicos. Si el
El valor de dicha expresión lógica se puede determinar sin evaluar una subexpresión, un
Se permite que el procesador no evalúe la subexpresión. Un ejemplo es
i <= 10. y. ary (i) == 0
! para una matriz real ary (10)
cuando tengo el valor 11. Sin embargo, el programador no debe confiar en tal comportamiento - un out-
se puede hacer referencia al subíndice de límites si el procesador elige evaluar el lado derecho
subexpresión antes de la izquierda. Volvemos a este tema en la Sección 5.10.1.
3.7 Expresiones y asignaciones de caracteres escalares
El único operador intrínseco para las expresiones de caracteres es el operador de concatenación //, que
tiene el efecto de combinar dos operandos de caracteres en un solo resultado de carácter. Por ejemplo,
El resultado de concatenar las constantes de dos caracteres AB y CD, escritas como
'A B C D'
es la cadena de caracteres ABCD. Los operandos deben tener los mismos valores de parámetros amables, pero pueden
ser variables de caracteres, constantes o funciones. Por ejemplo, si word1 y word2 son ambas
tipo y longitud predeterminados 4, y contienen las cadenas de caracteres LOOP y HOLE, respectivamente, el
string POLE es el resultado de
palabra1 (4: 4) // palabra2 (2: 4)

Página 14
Expresiones y tareas 41
La longitud del resultado de una concatenación es la suma de las longitudes de los operandos. Así,
la longitud del resultado de
palabra1 // palabra2 // 'S'
es 9, que es la longitud de la cadena LOOPHOLES.
El resultado de una expresión de caracteres puede asignarse a una variable de caracteres de la misma
tipo. Asumiendo las declaraciones
carácter (len = 4) :: char1, char2
carácter (len = 8) :: resultado
podemos escribir
char1 = 'any'
char2 = 'libro'
resultado = char1 // char2
En este caso, el resultado ahora contendrá la cadena de cualquier libro. Observamos en estos ejemplos que
Las longitudes de los lados izquierdo y derecho de las tres asignaciones son iguales en cada caso.
Sin embargo, si la longitud del resultado del lado derecho es más corta que la longitud del
lado izquierdo, luego el resultado se coloca en la parte más a la izquierda del lado izquierdo y el resto
está lleno de caracteres en blanco. Por lo tanto, en
carácter (len = 5) :: relleno
fill (1: 4) = 'AB'
fill (1: 4) tendrá el valor ABbb (donde b representa un carácter en blanco). El valor de
fill (5: 5) permanece indefinido, es decir, no contiene ningún valor específico y no debe usarse
En una expresión. Como consecuencia, el relleno también está indefinido. Por otro lado, cuando el
el lado izquierdo es más corto que el resultado del lado derecho, el extremo derecho del resultado
está truncado El resultado de
personaje (len = 5) :: trunc8
trunc8 = 'TRUNCATE'
es colocar en trunc8 la cadena de caracteres TRUNC. Si un lado izquierdo es de longitud cero, no
Asignación tiene lugar.
Los lados izquierdo y derecho de una tarea pueden superponerse. En tal caso, siempre es
los valores antiguos que se usan en la expresión del lado derecho. Por ejemplo, la tarea
resultado (3: 5) = resultado (1: 3)
es válido y si el resultado comienza con el valor ABCDEFGH, quedaría con el valor
ABABCFGH.
Otros medios para manipular caracteres y cadenas de caracteres, mediante funciones intrínsecas,
se describen en las Secciones 9.6 y 9.7.
3.7.1 Conjunto de caracteres ASCII
Si el juego de caracteres predeterminado para un procesador no es ASCII, pero ASCII es compatible con eso
procesador, la asignación intrínseca se define entre ellos para convertir caracteres adecuadamente.
Por ejemplo, en una máquina EBCDIC, en

Página 15
42 Fortran moderno explicado
entero, parámetro :: ascii = selected_char_kind ('ASCII')
personaje
:: ce
personaje (ascii)
:: ca
ce = ascii_'X '
ca = 'X'
la primera instrucción de asignación convertirá la X mayúscula ASCII en una mayúscula EBCDIC
X, y la segunda declaración de asignación hará lo contrario.
3.7.2 Conjunto de caracteres ISO 10646
ISO / IEC 10646 UCS-4 es un juego de caracteres de cuatro bytes diseñado para poder representar cada
caracteres en todos los idiomas del mundo, incluidos todos los caracteres especiales en uso en otros códigos
juegos de caracteres Es un superconjunto estricto de ASCII de siete bits; es decir, sus primeros 128 caracteres son los
igual que los de ASCII.
Se permite la asignación de caracteres predeterminados o caracteres ASCII a ISO 10646, y el
los caracteres se convierten apropiadamente. Asignación de caracteres ISO 10646 al valor predeterminado o
Los caracteres ASCII también están permitidos; sin embargo, si algún carácter ISO 10646 no es representable
en el juego de caracteres de destino, el resultado depende del procesador (se perderá información).
Por ejemplo, en
entero, parámetro :: ascii = selected_char_kind ('ASCII')
entero, parámetro :: iso10646 = selected_char_kind ('ISO_10646')
carácter (ascii) :: x = ascii_'X '
carácter (iso10646) :: y
y=x
la variable de caracteres ISO 10646 y se establecerá en el valor correcto para la letra mayúscula X.
3.8 Constructores de estructuras
Una estructura puede construirse a partir de expresiones para sus componentes, como una constante
La estructura puede construirse a partir de constantes (Sección 2.9). La forma general de una estructura.
el constructor es
derivado-tipo-especificación ([componente-especificación-lista])
donde derivada-tipo-especificación es el nombre de un tipo derivado 3 y cada componente-especificación es
[palabra clave =] expr
o
[keyword =] target
donde palabra clave es el nombre de un componente del tipo, expr es un valor para un no puntero
componente, y target es un objetivo para un componente puntero.
En un caso simple, las especificaciones del componente no tienen palabras clave y proporcionan valores para
componentes en el orden en que aparecen en la declaración de tipo. Por ejemplo, dado el tipo
3 Una forma más general se discutirá en la Sección 13.2.

Página 16
Expresiones y tareas 43
tipo char10
entero
:: longitud
carácter (len = 10) :: valor
tipo final char10
y las variables
carácter (len = 4) :: char1, char2
El siguiente es un valor de tipo char10:
char10 (8, char1 // char2)
Si se usan palabras clave, deben aparecer después de cualquier especificación de componente sin palabras clave pero
Puede estar en cualquier orden. Ningún componente puede aparecer más de una vez. Un componente puede ser
ausente solo si tiene una inicialización predeterminada (Sección 8.5.5).
Los componentes sin puntero se tratan como si la instrucción de asignación intrínseca
derivado-tipo-especificación% palabra clave = expr
se ejecutó y los componentes del puntero se tratan como si la instrucción de asignación del puntero
derivado-tipo-especificación% palabra clave => objetivo
Había sido ejecutado. En ambos casos, las reglas para la asignación intrínseca y la asignación del puntero
aplicar. 4 4
3.9 Operadores definidos escalares
No hay operadores para tipos derivados disponibles automáticamente. Si un programador define un derivado
tipo y desea que los operadores estén disponibles, él o ella también deben definir los operadores. Para
operador binario esto se hace escribiendo una función, con dos intenciones en los argumentos, que especifica
cómo el resultado depende de los operandos y un bloque de interfaz que asocia la función
con el token del operador (las funciones, la intención y los bloques de interfaz se explicarán completamente en
Capítulo 5). Por ejemplo, dado el tipo
intervalo de tipo
real :: inferior, superior
intervalo de tipo final
que representa intervalos de números entre un límite inferior y uno superior, podemos definir
adición por un módulo (Sección 5.5) que contiene el procedimiento
función add_interval (a, b)
tipo (intervalo)
:: add_interval
tipo (intervalo), intento (in) :: a, b
add_interval% lower = a% lower + b% lower! Código de producción
add_interval% upper = a% upper + b% upper! permitir el redondeo.
función final add_interval
y el bloque de interfaz (Sección 5.18)
4 En particular, el objetivo no debe ser una constante.

Página 17
44 Fortran moderno explicado
operador de interfaz (+)
procedimiento de módulo add_interval
interfaz final
Esta función se invocaría en una expresión como
y+z
para realizar esta operación de adición definida por el programador para las variables escalares y y z de tipo
intervalo. Un operador unario se define por un bloque de interfaz y una función con una sola intención.
en argumento
El token del operador puede ser cualquiera de los tokens utilizados para los operadores intrínsecos o puede ser un
secuencia de hasta 63 letras encerradas en puntos decimales que no sean verdaderos. o .false .. Un
ejemplo es
.suma.
En este caso, la línea de encabezado del bloque de interfaz se escribiría como
operador de interfaz (.sum.)
y la expresión como
y.sum.z
Si se utiliza un token intrínseco, el número de argumentos debe ser el mismo que para el intrínseco.
operación, la precedencia de la operación es como para la operación intrínseca y unario
menos o más no debe seguir inmediatamente después de otro operador. De lo contrario, es de mayor
precedencia para operadores unarios definidos y precedencia más baja para operadores binarios definidos.
El conjunto completo de precedencia se da en la Tabla 3.4. Donde se requiere otra precedencia
dentro de una expresión, se deben usar paréntesis.
Tabla 3.4. Precedencia relativa de los operadores (en orden decreciente).
Tipo de operación cuando es intrínseca
Operador
-
operador definido monádico (unario)
Numérico
** **
Numérico
*o/
Numérico
monádico + o -
Numérico
diádico + o -
Personaje
//
Relacional
==
/=
<
<=
>
>=
Lógico
.no.
Lógico
.y.
Lógico
.o.
Lógico
.eqv. o .neqv.
-
operador definido diádico (binario)

Página 18
Expresiones y tareas 45
Retener las precedencia intrínsecas es útil tanto para la legibilidad de las expresiones como para
La eficiencia con la que un compilador puede interpretarlos. Por ejemplo, si + se usa para establecer
union y * para establecer intersección, podemos interpretar la expresión
i*j+k
para los conjuntos i, j y k sin dificultad.
Si alguno de los tokens intrínsecos == y .eq. se usa, la definición se aplica a ambos tokens
que siempre son equivalentes Lo mismo es cierto para los otros pares equivalentes de relaciones
operadores
Tenga en cuenta que un operador unario definido que no utiliza un token intrínseco puede seguir inmediatamente
después de otro operador, como en
y .sum. .inverso. X
Los operadores se pueden definir para cualquier tipo de operandos, excepto donde hay un intrínseco
operación para el operador y tipos. Por ejemplo, podríamos desear poder agregar un
número de intervalo a un real ordinario, que se puede hacer con el procedimiento adicional
función add_interval_real (a, b)
tipo (intervalo)
:: add_interval_real
tipo (intervalo), intento (in) :: a
real, intención (en)
:: b
add_interval_real% lower = a% lower + b! Código de producción
add_interval_real% upper = a% upper + b! permitir el redondeo.
función final add_interval_real
cambiando el bloque de interfaz a
operador de interfaz (+)
procedimiento de módulo add_interval, add_interval_real
interfaz final
El resultado de tal operación definida puede tener cualquier tipo. El tipo de resultado, también
como su valor, debe ser especificado por la función.
Tenga en cuenta que una operación que se define intrínsecamente no se puede redefinir; así en
real :: a, b, c
...
c=a+b
El significado de la operación es siempre inequívoco.
3.10 Asignaciones definidas escalares
La asignación de una expresión de tipo derivado a una variable del mismo tipo es automáticamente
disponible y se lleva a cabo componente por componente. Por ejemplo, si a es del tipo intervalo
definido al comienzo de la Sección 3.9, podemos escribir
a = intervalo (0.0, 1.0)
(los constructores de estructuras se cumplieron en la Sección 3.8).

Página 19
46 Fortran moderno explicado
En otras circunstancias, sin embargo, podríamos querer definir una acción diferente para un
asignación que involucra un objeto de tipo derivado, y de hecho esto es posible. Un trabajo
puede redefinirse u otra asignación puede definirse mediante una subrutina con dos argumentos,
el primero tiene intención de salir o intento de salida y corresponde a la variable, y el segundo
teniendo intención y correspondiente a la expresión (las subrutinas también se tratarán completamente
en el Capítulo 5). En el caso de una asignación que involucra un objeto de tipo derivado y un objeto
de un tipo diferente, se debe proporcionar dicha definición. Por ejemplo, asignación de reales a
intervalos y viceversa podrían definirse por un módulo que contiene las subrutinas
subrutina real_de_intervalo (a, b)
real, intencional
:: una
tipo (intervalo), intento (in) :: b
a = (b% más bajo + b% más alto) / 2
fin subrutina real_de_intervalo
y
subrutina intervalo_de_real_ (a, b)
tipo (intervalo), intento (fuera) :: a
real, intención (en)
:: b
a% más bajo = b
a% superior = b
subrutina final intervalo_de_real
y el bloque de interfaz
asignación de interfaz (=)
procedimiento de módulo real_de_intervalo, intervalo_de_real_
interfaz final
Dado esto, podemos escribir
tipo (intervalo) :: a
a = 0.0
Una asignación definida no debe redefinir el significado de una asignación intrínseca para
tipos intrínsecos, es decir, una asignación entre dos objetos de tipo numérico, de tipo lógico,
o de tipo de carácter con el mismo parámetro amable, pero puede redefinir el significado de un
asignación intrínseca para dos objetos del mismo tipo derivado. Por ejemplo, para una tarea
entre dos variables del tipo char10 (Sección 3.9) que copia solo la parte relevante de
el componente del personaje, podríamos escribir
subrutina asignar_cadena (izquierda, derecha)
type (char10), intent (out) :: left
type (char10), intent (in) :: right
izquierda% longitud = derecha% longitud
left% value (1: left% length) = right% value (1: right% length)
finalizar subrutina asignar_cadena
La asignación intrínseca para un objeto de tipo derivado siempre implica una asignación intrínseca para todos
sus componentes sin puntero, incluso si un componente es de un tipo derivado para el que se asigna
ha sido redefinido

Página 20
Expresiones y tareas 47
3.11 Expresiones de matriz
Hasta ahora en este capítulo hemos asumido que todas las entidades en una expresión son escalares.
Sin embargo, cualquiera de las operaciones intrínsecas unitarias también puede aplicarse a una matriz para producir
otra matriz de la misma forma (rango y extensión idénticos, ver Sección 2.10) y tener
cada valor de elemento igual al de la operación aplicada al elemento correspondiente de la
operando Del mismo modo, las operaciones intrínsecas binarias pueden aplicarse a un par de matrices de la misma.
forma para producir una matriz de esa forma, con cada valor de elemento igual al de la operación
aplicado a los elementos correspondientes de los operandos. Uno de los operandos de una operación binaria.
puede ser un escalar, en cuyo caso el resultado es como si el escalar se hubiera transmitido a una matriz de
la misma forma que el conjunto de operandos. Dadas las declaraciones de matriz
real, dimensión (10,20) :: a, b
real, dimensión (5)
:: v
Los siguientes son ejemplos de expresiones de matriz:
a/b
! Matriz de forma [10,20], con elementos a (i, j) / b (i, j)
v + 1.
! Matriz de forma [5], con elementos v (i) +1.0
5 / v + a (1: 5,5)! Matriz de forma [5], con elementos 5 / v (i) + a (i, 5)
a == b
! Matriz lógica de forma [10,20], con elemento (i, j)
! .cierto. si a (i, j) == b (i, j), y .false. de otra manera
Se dice que dos matrices de la misma forma son conformables, y un escalar es conformable con
cualquier conjunto
Tenga en cuenta que la correspondencia es por posición en la extensión y no por valor de subíndice. por
ejemplo,
a (2: 9,5: 10) + b (1: 8,15: 20)
tiene valores de elementos
a (i + 1, j + 4) + b (i, j + 14)
donde i = 1, 2,. . . , 8, j = 1,2, ..., 6
Esto puede representarse gráficamente como en la Figura 3.1.
El orden en que se ejecutan las operaciones escalares en cualquier expresión de matriz no es
especificado en el estándar, permitiendo así que un compilador organice una ejecución eficiente en un vector
o computadora paralela.
Cualquier operador intrínseco escalar se puede aplicar de esta manera a matrices y matrices-escalares.
pares. Para operadores derivados, el programador puede definir un procedimiento elemental con estos
propiedades (ver Sección 7.9). Él o ella también puede definir operadores directamente para ciertos rangos o
pares de filas Por ejemplo, el tipo
tipo de matriz
real :: elemento
matriz de tipo final
podría definirse para tener operaciones escalares que sean idénticas a las operaciones para reales, pero
para las matrices de los rangos uno y dos, el operador * se define como multiplicación matricial media. los
Por lo tanto, el tipo de matriz sería adecuado para la aritmética de la matriz, mientras que los reales no son adecuados
porque la multiplicación de matrices reales se realiza elemento por elemento. Esto se discute más a fondo
en la Sección 7.5.

Página 21
48 Fortran moderno explicado
Figura 3.1 La suma de dos secciones de matriz.
3.12 Asignación de matriz
Por asignación intrínseca, se puede asignar una expresión de matriz a una variable de matriz de
misma forma, 5 que se interpreta como si cada elemento de la expresión fuera asignado a
elemento correspondiente de la variable. Por ejemplo, con las declaraciones del comienzo
de la última sección, la tarea
a = a + 1.0
reemplaza a (i, j) por a (i, j) +1.0 para i = 1, 2, ..., 10 y j = 1, 2, ..., 20. Tenga en cuenta que, como
para expresiones, la correspondencia del elemento es por posición dentro de la extensión en lugar de por
valor del subíndice Esto se ilustra con el ejemplo.
a (1,11: 15) = v
! a (1, j + 10) se asigna desde
! v (j), j = 1, 2, ..., 5
Se puede asignar una expresión escalar a una matriz, en cuyo caso se transmite el valor escalar
a todos los elementos de la matriz.
Si la expresión incluye una referencia a la variable de matriz o a una parte de ella, la expresión
se interpreta como una evaluación completa antes de que comience la asignación. Por ejemplo, el
declaración
v (2: 5) = v (1: 4)
5 Para las matrices asignables, las formas pueden diferir, consulte la Sección 6.7.
+
=
resultado
8x6
a (1,1)
a (1,20)
a (2,5)
a (2,10)
a (9,5)
a (9,10)
a (10,1)
a (10,20)
) 51,1 (b
) 1,1 (b
b (1,20)
b (8,15)
b (8,20)
b (10,1)
b (10,20)

Página 22
Expresiones y tareas 49
da como resultado que cada elemento v (i) para i = 2, 3, 4, 5 tenga el valor que v (i-1) tenía antes del
comienzo de la tarea. Esta regla es exactamente paralela a la regla para las subcadenas que era
explicado en la Sección 3.7. No se especifica el orden en que se asignan los elementos de la matriz.
por el estándar, para permitir optimizaciones.
Conjuntos de funciones intrínsecas numéricas y matemáticas, cuyos resultados pueden usarse como
los operandos en expresiones escalares o de matriz y en asignaciones se describen en las Secciones 9.3
y 9.4.
Si una asignación definida (Sección 3.10) se define mediante una subrutina elemental (Sección 7.9),
se puede usar para asignar un valor escalar a una matriz o un valor de matriz a una matriz de
Misma forma. Se puede proporcionar una subrutina separada para cualquier combinación particular de rangos
y anulará la asignación elemental. Si no hay una asignación definida elemental,
La asignación intrínseca todavía está disponible para aquellas combinaciones de rangos para las que no hay
asignación definida correspondiente.
Una forma de asignación de matriz bajo una máscara se describe en la Sección 7.6 y asignación
expresado con la ayuda de índices en el Apéndice B.3.1.
3.13 Punteros en expresiones y tareas
Un puntero puede aparecer como una variable en las expresiones y asignaciones que tenemos
considerado hasta ahora en este capítulo, siempre que tenga una asociación válida con un objetivo. El objetivo
se accede sin necesidad de un símbolo de desreferencia explícito. En particular, si ambos lados
de una instrucción de asignación son punteros, los datos se copian de un objetivo al otro objetivo.
A veces surge la necesidad de otro tipo de tarea. Podemos querer la mano izquierda
puntero para apuntar a otro objetivo, en lugar de que su objetivo actual adquiera datos nuevos. Es decir,
queremos que se modifique el descriptor. Esto se llama asignación de puntero y tiene lugar en un
declaración de asignación de puntero:
puntero => objetivo
donde puntero es el nombre de un puntero o el designador de un componente de estructura que es
un puntero, y el objetivo suele ser una variable, pero también puede ser una referencia a un puntero
función (ver Sección 5.10). Por ejemplo, las declaraciones
x => z
a => c
tienen variables como objetivos y son necesarias para la primera multiplicación matricial de la Sección 2.12, en
para hacer que x se refiera a z y a para referirse a c. La declaración
x => nulo ()
(la función nulo se describe en la Sección 9.17) anula x. La asignación del puntero también requiere
lugar para un componente de puntero de una estructura cuando la estructura aparece en el lado izquierdo
de una tarea ordinaria. Por ejemplo, supongamos que hemos usado la entrada de tipo de la Figura 2.3
de la Sección 2.12 para construir una cadena de entradas y desea agregar una nueva entrada al frente. Si
primeros puntos a la primera entrada y actual es un puntero escalar de entrada de tipo, las declaraciones
asignar (actual)
current = entry (new_value, new_index, first)
primero => actual

Página 23
50 Fortran moderno explicado
asignar una nueva entrada y vincularla a la parte superior de la cadena. La declaración de asignación tiene el
efecto
% actual siguiente => primero
y establece el enlace. La instrucción de asignación de puntero da primero la nueva entrada como su
objetivo sin alterar la primera entrada anterior. La tarea ordinaria
primero = actual
sería incorrecto porque el objetivo sería copiado, destruyendo la primera entrada anterior,
correspondiente a las asignaciones de componentes
primer% valor = valor actual%
! Componentes de la
primer% index =% index actual
! los viejos primero se pierden.
primer% siguiente => actual% siguiente
!
En el caso donde la cadena comenzó con longitud dos y consistió en
primero :
(1.0, 10, asociado)
primer% siguiente: (2.0, 15, nulo)
después de la ejecución del primer conjunto de declaraciones, tendría una longitud de tres y consistiría en
primero :
(4.0, 16, asociado)
primer% siguiente:
(1.0, 10, asociado)
primer% siguiente% siguiente: (2.0, 15, nulo)
Si el objetivo en una instrucción de asignación de puntero es una variable que no es en sí misma un puntero o un
Subobjeto de un puntero de destino, debe tener el atributo de destino. Por ejemplo, la declaración
real, dimensión (10), objetivo :: y
declara y para tener el atributo de destino. Cualquier subobjeto sin puntero de un objeto con el
El atributo target también tiene el atributo target. El atributo de destino es necesario para
propósito de la optimización del código por parte del compilador. Es muy útil para el compilador saber que
un objetivo puntero no puede acceder a una variable que no sea un puntero o un objetivo.
El objetivo en una instrucción de asignación de puntero puede ser un subobjeto de un objetivo de puntero. por
ejemplo, dada la declaración
carácter (len = 80), dimensión (:), puntero :: página
y una asociación apropiada, los siguientes son todos los objetivos permitidos:
página, página (10), página (2: 4), página (2) (3:15)
Tenga en cuenta que es suficiente que el puntero esté en cualquier nivel de selección de componentes. Por ejemplo,
dada la declaración
tipo (entrada) :: nodo
que tiene un componente de puntero a continuación (ver Sección 2.12) y una asociación apropiada,
El nodo% next% value es un objetivo permitido.
Si el objetivo en una instrucción de asignación de puntero es en sí mismo un objetivo de puntero, entonces un
Se realiza una copia directa del descriptor. Si el estado de asociación del puntero no está definido o
disociado, este estado se copia.
Si el objetivo es un puntero o un subobjeto de un objetivo puntero, la nueva asociación es con ese
destino del puntero y no se ve afectado por ningún cambio posterior en su estado de asociación de puntero.
Esto se ilustra en el siguiente ejemplo. La secuencia

Página 24
Expresiones y asignaciones 51
b => c
! c tiene el atributo de destino
a => b
anular (b)
dejará un todavía apuntando a c.
El tipo, los parámetros de tipo y el rango del puntero y el destino en una asignación de puntero
La declaración debe ser la misma. Si el puntero es una matriz, toma su forma y límites
del objetivo Los límites son los que devolverían las funciones lbound y ubound
(Sección 9.14.2) para el destino, lo que significa que una sección de matriz o expresión de matriz suele ser
tomado para tener el valor 1 para un límite inferior y la extensión para el límite superior correspondiente
(pero veremos más adelante cómo se puede especificar un límite inferior, consulte la Sección 7.15).
Fortran es inusual al no requerir un personaje especial para una referencia a un objetivo de puntero,
pero requiere uno para distinguir la asignación del puntero de la asignación ordinaria. La razón
para esta elección se esperaba que la mayoría de los programas de ingeniería y científicos se refieran a
datos de destino con mucha más frecuencia de lo que cambian los objetivos.
3.14 La declaración de anulación
Un puntero puede desasociarse explícitamente de su objetivo ejecutando una declaración nula.
Su forma general es
anular (puntero-objeto-lista)
No debe haber dependencias entre los objetos, para permitir que el procesador anule
los objetos uno por uno en cualquier orden. La declaración también es útil para dar a los disociados
estado a un puntero indefinido. Una ventaja de anular punteros en lugar de dejarlos
indefinido es que luego pueden ser probados por la función intrínseca asociada (Sección 9.2).
Por ejemplo, el final de la cadena de la Sección 3.13 se marcará como un puntero desasociado si
la declaración
anular (primero)
se ejecuta inicialmente para crear una cadena de longitud cero. Porque a menudo hay otras formas de acceder
un objetivo (por ejemplo, a través de otro puntero), la declaración de anulación no se desasigna
los objetivos Si también se requiere desasignación, una declaración de desasignación (Sección 6.6) debe ser
ejecutado en su lugar.
3.15 Resumen
En este capítulo hemos visto cómo las expresiones escalares y de matriz de caracteres numéricos, lógicos,
y los tipos derivados pueden formarse, y cómo las asignaciones correspondientes de los resultados pueden
hacerse. También se han presentado las expresiones relacionales y el uso de punteros. Nosotros
ahora tiene la información requerida para escribir secciones cortas de código formando una secuencia de
declaraciones que se realizarán una tras otra. En el siguiente capítulo veremos cómo
Se pueden construir secuencias más complicadas, que implican ramificación e iteración.

Página 25
52 Fortran moderno explicado
Ejercicios
1. Si todas las variables son escalares numéricos, ¿cuáles de las siguientes son expresiones numéricas válidas?
a+b
-C
a + -c
d + (- f)
(a + c) ** (p + q)
(a + c) (p + q)
- (x + y) ** i
4. ((ad) - (a + 4. * x) +1)
2. En las siguientes expresiones, agregue los paréntesis que corresponden a las reglas de precedencia de Fortran
(suponiendo que a, c – f son escalares reales, i – n son escalares lógicos yb es una matriz lógica); por ejemplo,
a + d ** 2 / c se convierte en a + ((d ** 2) / c).
c + 4. * f
4. * g-a + d / 2.
a ** e ** c ** d
a * ec ** d / a + e
yo y. j .or. k
.no. l .or. .no. yo y. m .neqv. norte
b (3). y.b (1) .o.b (6) .o..no.b (2)
3. ¿Cuáles son los resultados de las siguientes expresiones?
3 + 4/2
6/4/2
3. * 4 ** 2
3. ** 3/2
-1. ** 2
(-1.) ** 3
4. Una variable de carácter escalar r tiene una longitud ocho. ¿Cuáles son los contenidos de r después de cada uno de los
siguientes
tareas?
r = 'ABCDEFGH'
r = 'ABCD' // '01234'
r (: 7) = 'ABCDEFGH'
r (: 6) = 'ABCD'
5. ¿Cuál de las siguientes expresiones lógicas son válidas si b es una matriz lógica?
.not.b (1) .and.b (2)
.or.b (1)
b (1) .o..no.b (4)
b (2) (. y.b (3) .o.b (4))
6. Si todas las variables son escalares reales, ¿cuáles de las siguientes expresiones relacionales son válidas?
d <= c
p <t> 0
x-1 / = y
x + y <3 .or. > 4.
d <c. y 3.0
q == r. y. s> t
7. Escribe expresiones para calcular:
a) el perímetro de un cuadrado del lado l;
b) el área de un triángulo de base b y altura h;
c) el volumen de una esfera de radio r.
8. Un artículo cuesta n centavos. Escriba una declaración de declaración para variables adecuadas y asignación
declaraciones que calculan el cambio que se dará de una factura de $ 1 para cualquier valor de n de 1 a
99, utilizando monedas de denominación 1, 5, 10 y 25 centavos.
Expresiones y tareas 53
9. Dada la declaración de tipo para intervalo en la Sección 3.9, las definiciones de + dadas en la Sección 3.9,
las definiciones de asignación dadas en la Sección 3.10, y las declaraciones
tipo (intervalo) :: a, b, c, d
real
:: r
¿Cuál de las siguientes afirmaciones es válida?
a=b+c
c = b + 1.0
d=b+1
r=b+c
a=r+2
10. Dadas las declaraciones de tipo
real, dimensión (5,6) :: a, b
real, dimensión (5)
:: C
¿Cuál de las siguientes afirmaciones es válida?
a=b
c = a (:, 2) + b (5,: 5)
a = c + 1.0
c = a (2, :) + b (:, 5)
a (:, 3) = c
b (2:, 3) = c + b (: 5,3)

Página 2

Página 3

4. Construcciones de control
4.1 Introducción
Hemos aprendido en el capítulo anterior cómo se pueden escribir las declaraciones de asignación y cómo
estos pueden ordenarse uno tras otro para formar una secuencia de código que se ejecuta paso
Por paso. Sin embargo, en la mayoría de los cálculos, esta simple secuencia de declaraciones es en sí misma
inadecuado para la formulación del problema. Por ejemplo, podemos desear seguir uno
de dos posibles rutas a través de una sección de código, dependiendo de si un valor calculado es
positivo o negativo. Es posible que deseemos sumar 1000 elementos de una matriz, y hacer esto escribiendo
1000 adiciones y tareas es claramente tedioso; la capacidad de iterar sobre una sola adición
se requiere en su lugar. Es posible que deseemos pasar el control de una parte de un programa a otra, o
incluso deja de procesar por completo.
Para todos estos propósitos, tenemos disponibles en Fortran varias instalaciones para permitir la lógica
fluir a través de las declaraciones del programa que se controlarán. La forma más importante es la de
una construcción de bloque, que comienza con una declaración de palabra clave inicial, puede tener un intermedio
declaraciones de palabras clave y termina con una declaración de terminal coincidente; solo se puede ingresar en
La declaración inicial. Cada secuencia de declaraciones entre declaraciones de palabras clave se denomina
bloquear. Un bloque puede estar vacío, aunque estos casos son raros.
Las construcciones de bloque pueden estar anidadas, es decir, un bloque puede contener otra construcción de bloque. En
En tal caso, el bloque debe contener la totalidad de la construcción interna. Ejecución de un bloque
siempre comienza con su primera declaración.
4.2 El constructo if y la declaración
La construcción if contiene una o más secuencias de enunciados (bloques), como máximo una de las cuales
Es elegido para la ejecución. La forma general se muestra en la Figura 4.1. Aquí y en todo el
libro usamos corchetes para indicar elementos opcionales, seguidos de puntos si puede haber
número (incluido cero) de dichos artículos. Puede haber cualquier número (incluido cero) de otra cosa
declaraciones if, y cero o una declaración más. La nomenclatura es opcional, pero un else o else si
la declaración solo se puede nombrar si las declaraciones correspondientes if y end if se nombran, y
debe tener el mismo nombre. El nombre puede ser cualquier nombre de Fortran válido y distinto (ver
Sección 5.15 para una discusión sobre el alcance de los nombres).
Fortran moderno explicado, 2da edición. Michael Metcalf, John Reid y Malcolm Cohen. prensa de la Universidad de Oxford
(2018) cG Michael Metcalf, John Reid y Malcolm Cohen 2018. DOI 10.1093 / oso / 9780198811893.001.0001

Página 4
56 Fortran moderno explicado
Figura 4.1 La construcción if.
[nombre:] if (scalar-logical-expr) entonces
bloquear
[si if (scalar-logical-expr) entonces [nombre]
bloque]. . .
[más [nombre]
bloque]
finalizar si [nombre]
Un ejemplo de la construcción if en su forma más simple es
intercambio: si (x <y) entonces
temp = x
x=y
y = temp
terminar si intercambio
El bloque de tres declaraciones se ejecuta si la condición es verdadera; de lo contrario ejecución
continúa desde la declaración que sigue al final de la declaración if. Tenga en cuenta que el bloque interior
la construcción if está sangrada. Esto no es obligatorio, pero hace que la lógica sea más fácil de entender,
especialmente en construcciones anidadas if como veremos al final de esta sección.
La siguiente forma más simple tiene un bloque else, pero no otra si if blocks. Ahora hay un
bloque alternativo para el caso donde la condición es falsa. Un ejemplo es
si (x <y) entonces
x = -x
más
y = -y
terminara si
en el que el signo de x cambia si x es menor que y, y el signo de y cambia si x es mayor
que o igual a y.
El tipo más general de construcción if usa la instrucción else if para hacer una sucesión de
pruebas, cada una de las cuales tiene su bloque de declaraciones asociado. Las pruebas se realizan una después de la
otro hasta que se cumpla uno, y las declaraciones asociadas del bloque relevante if o else if
son ejecutados El control luego pasa al final de la construcción if. Si no se realiza ninguna prueba, no
el bloque se ejecuta, a menos que haya una cláusula final 'catch-all' else.
Hay una forma abreviada útil para el caso más simple de todos. Una construcción if del formulario
if (scalar-logical-expr) entonces
acción-stmt
terminara si
puede ser escrito
if (scalar-logical-expr) action-stmt
Ejemplos son
si (xy> 0.0) x = 0.0
if (cond. o. p <q. y. r <= 1.0) s (i, j) = t (j, i)

Página 5
Control de construcciones 57
Se permite anidar si las construcciones tienen una profundidad arbitraria, como se muestra en dos niveles en
Figura 4.2, en la que vemos la necesidad de sangrar el código para poder entender
La lógica fácilmente. Para un anidamiento aún más profundo, se recomienda nombrar. Las construcciones deben
estar debidamente anidado; es decir, cada construcción debe estar totalmente contenida en un bloque de la siguiente
construcción exterior.
Figura 4.2 Una construcción anidada if.
si (i <0) entonces
si (j <0) entonces
x = 0.0
y = 0.0
más
z = 0.0
terminara si
de lo contrario si (k <0) entonces
z = 1.0
más
x = 1.0
y = 1.0
terminara si
4.3 La construcción del caso
Fortran proporciona otro medio de seleccionar una de varias opciones, bastante similar a la de
la construcción if. Las principales diferencias entre las dos construcciones son que, para el caso
construir, solo se evalúa una expresión para la prueba, y la expresión evaluada puede
pertenecer a no más de uno de una serie de conjuntos de valores predefinidos. La forma del caso
la construcción se muestra por:
[nombre:] seleccione caso (expr)
[selector de caso [nombre]
bloque]. . .
fin seleccione [nombre]
En cuanto a la construcción if, las declaraciones iniciales y finales deben estar sin nombre
o ambos llevan el mismo nombre; una declaración de caso dentro de ella solo se puede nombrar si
la declaración se nombra y lleva el mismo nombre. La expresión expr debe ser escalar y de
escriba carácter, lógico o entero, y los valores especificados en cada selector deben ser de este
tipo. En el caso de los caracteres, las longitudes pueden diferir, pero no los tipos. En la lógica
y casos enteros, los tipos pueden diferir. La forma más simple de selector es una constante escalar
expresión 1 entre paréntesis, como en la declaración
1 Una expresión constante es una forma restringida de expresión que puede verificarse como constante (las restricciones son
elegido para facilitar la implementación). Los detalles son tediosos y se remiten a la Sección 8.4. En esta sección, todos
Los ejemplos emplean la forma más simple de expresión constante: la constante literal.

Página 6
58 Fortran moderno explicado
caso 1)
Para el carácter o entero expr, un rango puede especificarse mediante una constante escalar inferior y superior
expresión separada por dos puntos:
caso (bajo: alto)
Puede estar ausente bajo o alto, pero no ambos. esto es equivalente a especificar que el caso
se selecciona cada vez que expr evalúa un valor que es menor o igual que alto o mayor
que o igual a bajo, respectivamente. Un ejemplo se muestra en la Figura 4.3.
Figura 4.3 Una construcción de caso.
seleccione caso (número)
! el número es de tipo entero
caso 1)
! todos los valores por debajo de 0
n_sign = -1
caso (0)
! solo 0
n_sign = 0
caso 1:)
! todos los valores superiores a 0
n_sign = 1
seleccione final
La forma general de selector es una lista de valores y rangos no superpuestos, todos iguales
escriba como expr, entre paréntesis, como
caso (1, 2, 7, 10:17, 23)
La forma
caso predeterminado
es equivalente a una lista de todos los valores posibles de expr que no están incluidos en el otro
selectores de la construcción. Aunque recomendamos que los valores estén en orden, como en este
ejemplo, esto no es obligatorio. No se permiten valores superpuestos dentro de un selector, ni
entre diferentes en la misma construcción.
Solo puede haber un selector predeterminado de un solo caso en una construcción de caso dada, como se muestra en
Figura 4.4. La cláusula predeterminada del caso no necesariamente tiene que ser la última cláusula del
construcción de caso.
Figura 4.4 Una construcción de caso con un selector de caso predeterminado.
seleccione caso (ch)
! ch de tipo de letra
case ('c', 'd', 'r' :)
ch_type = .true.
case ('i': 'n')
int_type = .true.
caso predeterminado
tipo_ real = .verdadero.
seleccione final

Página 7
Construcciones de control 59
Dado que los valores de los selectores no pueden solaparse, a lo sumo un selector puede ser
satisfecho; Si ninguno está satisfecho, el control pasa a la siguiente instrucción ejecutable después de
declaración de selección final.
Al igual que la construcción if, las construcciones case pueden estar anidadas una dentro de otra.
4.4 La construcción do
Muchos problemas en matemáticas requieren la capacidad de iterar. Si deseamos sumar los elementos
de una matriz de longitud 10, podríamos escribir
suma = a (1)
suma = suma + a (2)
...
suma = suma + a (10)
lo cual es claramente laborioso. Fortran proporciona una instalación conocida como la construcción do que permite
nosotros para reducir estas diez líneas de código a
suma = 0.0
¿i = 1,10! i es de tipo entero
suma = suma + a (i)
fin hacer
En este fragmento de código, primero establecemos la suma en cero, y luego requerimos que la declaración entre
la declaración do y la declaración final do se ejecutarán diez veces. Para cada iteración
hay un valor asociado de un índice, mantenido en i, que asume el valor 1 para el primer
iteración a través del ciclo, 2 para el segundo, y así sucesivamente hasta 10. La variable i es normal
variable entera, pero está sujeta a la regla de que no debe modificarse explícitamente dentro del do
construir.
La declaración do tiene formas más generales. Si quisiéramos sumar los elementos cuarto a noveno
nosotros escribiriamos
¿i = 4, 9
especificando así los primeros y últimos valores requeridos de i. Si, alternativamente, deseamos sumar
todos los elementos impares, escribiríamos
¿i = 1, 9, 2
donde el tercero de los tres parámetros de bucle, a saber, el 2, especifica que i debe ser
incrementado en pasos de 2, en lugar de por el valor predeterminado de 1, que se supone si no hay un tercero
se da el parámetro De hecho, podemos ir más allá, ya que los parámetros no necesitan ser constantes en
todas, excepto expresiones enteras, como en
do i = j + 4, m, -k (j) ** 2
en el que el primer valor de i es j + 4, y los valores posteriores se reducen por k (j) ** 2 hasta
Se alcanza el valor de m. Por lo tanto, los índices pueden ejecutarse "hacia atrás" y "hacia adelante". Si alguna
de los tres parámetros es una variable o es una expresión que involucra una variable, el valor de
la variable puede modificarse dentro del bucle sin afectar el número de iteraciones, como
Los valores iniciales de los parámetros se utilizan para el control del bucle.

Página 8
60 Fortran moderno explicado
La forma general de este tipo de cláusula de control de construcción limitada es
[nombre:] do [,] variable = expr 1 , expr 2 [, expr 3 ]
bloquear
end do [nombre]
donde variable es una variable entera escalar con nombre, expr 1 , expr 2 y expr 3 (expr 3 debe ser
cuando no está presente) son expresiones enteras escalares válidas, y name es el opcional
nombre del constructo Las declaraciones do y end do deben estar sin nombre o llevar el mismo nombre.
El número de iteraciones de una construcción do viene dado por la fórmula
max
(expr 2 -expr 1 + expr 3
expr 3
,0
)
donde max es una función que veremos en la Sección 9.3.2 y que aquí devuelve
el valor de la primera expresión o cero, el que sea mayor. Hay una consecuencia
a partir de esta definición, a saber, que si un ciclo comienza con la declaración
do i = 1, n
entonces su cuerpo no se ejecutará en absoluto si el valor de n al ingresar al bucle es cero o menos.
Este es un ejemplo del ciclo de disparo cero, y resulta de la aplicación de la función max.
Una forma muy simple de la declaración do es lo ilimitado
[nombre:] hacer
que especifica un bucle sin fin. En la práctica, se requiere un medio para salir de un bucle sin fin,
y esto se proporciona en forma de la declaración de salida:
salir [nombre]
donde name es opcional y se usa para especificar desde qué construye la salida debe ser
tomado en el caso de construcciones anidadas. 2 La ejecución de una declaración de salida hace que el control
se transferirá a la siguiente instrucción ejecutable después de la instrucción de finalización a la que se refiere.
Si no se especifica ningún nombre, finaliza la ejecución de la construcción do más interna en la que está
adjunto. Como ejemplo de esta forma de hacer, supongamos que hemos usado la entrada de tipo de la Sección
2.12 para construir una cadena de entradas en un vector disperso, y deseamos encontrar la entrada con índice
10, se sabe que está presente. Si el primer punto apunta a la primera entrada, el código de la Figura 4.5 es adecuado.
Figura 4.5 Búsqueda de una lista vinculada.
tipo (entrada), puntero :: primero, actual
...
actual => primero
hacer
if (actual% index == 10) salir
actual => actual% siguiente
fin hacer
La declaración de salida también es útil en un bucle acotado cuando no todas las iteraciones son siempre
necesario.
Una declaración relacionada es la declaración del ciclo
2 De hecho, una salida con nombre se puede usar para salir de casi cualquier construcción, no solo un bucle; ver Sección 4.5.

Página 9
Control de construcciones 61
ciclo [nombre]
que transfiere el control al final hacer la declaración de la construcción correspondiente. Por lo tanto, si
Aún se deben realizar más iteraciones, se inicia la siguiente.
El valor de un índice de construcción (si está presente) se incrementa al final de cada ciclo
iteración para usar en la iteración posterior. Como el valor de este índice está disponible fuera de
bucle después de su ejecución, tenemos tres situaciones posibles, cada una ilustrada por lo siguiente
lazo:
do i = 1, n
...
si (i == j) sale
...
fin hacer
l=i
Las situaciones son las siguientes:
i) Si, en tiempo de ejecución, n tiene el valor cero o menos, se establece en 1 pero el bucle no es
ejecutado, y el control pasa a la declaración que sigue a la declaración de finalización.
ii) Si n tiene un valor mayor o igual a j, se tomará una salida en el if
declaración, y adquiriré el último valor de i, que por supuesto es j.
iii) Si el valor de n es mayor que cero pero menor que j, el bucle se ejecutará n veces,
con los valores sucesivos de i siendo 1,2, ..., n. Al llegar al final del ciclo para
la enésima vez, se incrementará una última vez, adquiriendo el valor n + 1, que
luego ser asignado a l.
Vemos lo importante que es hacer un uso cuidadoso de los índices de bucle fuera del bloque do, especialmente
cuando existe la posibilidad de que el número de iteraciones tome el valor límite de la
Máximo para el bucle.
El bloque do, que acabo de mencionar, es la secuencia de declaraciones entre la declaración do y
Al final hacer declaración. Está prohibido saltar a un bloque do o al final de la declaración do
en cualquier lugar fuera de la cuadra.
Es igualmente inválido para el bloque de una construcción do (o cualquier otra construcción, como un
if o case construct), para estar parcialmente contenido en un bloque de otra construcción. los
La construcción debe estar completamente contenida en el bloque. Las siguientes dos secuencias son válidas:
do i = 1, n
if (scalar-logical-expr) entonces
...
terminara si
fin hacer
y
if (scalar-logical-expr) entonces
do i = 1, n

Página 10
62 Fortran moderno explicado
...
fin hacer
más
...
terminara si
Cualquier cantidad de construcciones do puede estar anidada. Por lo tanto, podemos escribir una multiplicación matricial
como
se muestra en la figura 4.6.
Figura 4.6 Multiplicación de matrices como una construcción triplicada anidada.
do i = 1, n
hacer j = 1, m
a (i, j) = 0.0
do l = 1, k
a (i, j) = a (i, j) + b (i, l) * c (l, j)
fin hacer
fin hacer
fin hacer
Una forma adicional de do construct, la construcción concurrente do, se describe en la Sección 7.17,
y formas adicionales, pero redundantes, de sintaxis do en el Apéndice A.5.
Finalmente, debe notarse que muchos bucles cortos pueden expresarse alternativamente en el
forma de expresiones de matriz y asignaciones. Sin embargo, esto no siempre es posible, y un
Un peligro particular a tener en cuenta es cuando una iteración del bucle depende de una anterior.
Por lo tanto, el bucle
do i = 2, n
a (i) = a (i-1) + b (i)
fin hacer
no puede ser reemplazado por la declaración
a (2: n) = a (1: n-1) + b (2: n)
! Tener cuidado
4.5 Salida de casi cualquier construcción
La declaración de salida puede, de hecho, usarse para completar la ejecución de cualquier construcción excepto
la construcción concurrente do (ver Sección 7.17). Para hacer esto, la construcción debe ser
named y ese nombre usado en la declaración de salida. Un ejemplo de esto se muestra en la Figura 4.7.
Tenga en cuenta que una instrucción de salida sin un nombre de construcción sale de la construcción do más interna.
Dado que los diferentes comportamientos pueden confundir fácilmente, recomendamos que si una salida de un
La construcción do se usa cerca de una salida desde una construcción do (como en la Figura 4.7), ambas salidas
las declaraciones tienen etiquetas de construcción.
Tenga en cuenta que está prohibido salir de una construcción externa desde un punto crítico o
construcción concurrente.

Página 11
Construcciones de control 63
Figura 4.7 Salir de if construct.
add_to_set: if (add_x_to_set) entonces
find_position: do i = 1, size (set)
if (x == set (i)) salir add_to_set
if (x> set (i)) sale de find_position
end do find_position
set = [set (: i-1), x, set (i :)]! set se reasigna (ver Sección 6.7)
finalizar si agregar_a_set
4.6 El ir a la declaración
Solo ocasionalmente, especialmente cuando se trata de condiciones de error, el control construye que
que hemos descrito puede ser inadecuado para las necesidades del programador. El remedio es usar el
declaración más disputada en lenguajes de programación - la declaración go to - para ramificarse
Otra declaración. En general, se acepta que es difícil entender un programa que
es interrumpido por muchas ramas, especialmente si hay una gran cantidad de ramas hacia atrás
- aquellos que devuelven el control a una declaración que precede a la rama misma.
La forma de la declaración ir a incondicional es
ir a la etiqueta
donde etiqueta es una etiqueta de declaración. Esta etiqueta de declaración debe estar presente en un ejecutable
declaración (una declaración que se puede ejecutar, en lugar de una de carácter informativo, como
una declaración). Un ejemplo es
x = y + 3.0
ir a 4
3 x = x + 2.0
4z=x+y
en el que observamos que después de la ejecución de la primera declaración, se lleva una rama a la última
declaración, etiquetada 4. Esta es una declaración de destino de rama. La declaración etiquetada 3 es
saltó y solo se puede ejecutar si hay una rama en la etiqueta 3 en otro lugar.
Si la declaración que sigue a un ir incondicional no está etiquetada, nunca se puede alcanzar y
ejecutado, por lo tanto, es un código muerto, normalmente un signo de codificación incorrecta.
Las declaraciones dentro de un bloque de una construcción pueden etiquetarse, pero las etiquetas nunca deben ser
referenciado de tal manera que pase el control al rango de un bloque desde fuera de él, a un
else if declaración o a una declaración else. Está permitido pasar el control de una declaración en
una construcción a la declaración terminal de la construcción, o a una declaración fuera de su construcción.
La instrucción if se usa normalmente para realizar una sola asignación dependiendo de
una condición, o ramificarse dependiendo de una condición. La acción-stmt puede no estar etiquetada
por separado. Ejemplos son
si (bandera) pasa a 6
si (xy> 0.0) x = 0.0
La ramificación también puede ocurrir en una declaración de entrada / salida (Capítulo 10) con un err =, end = o
err = cláusula

Pagina 12
64 Fortran moderno explicado
4.7 Resumen
En este capítulo hemos presentado las cuatro características principales por las cuales el control en el código Fortran
puede programarse: la instrucción if y la construcción, la construcción del caso y el do
construir. El ir a la declaración también se ha mencionado. El uso efectivo de estas características
Es una clave para el código de sonido.
Hemos tocado el concepto de una unidad de programa como si fuera el capítulo de un libro.
Así como un libro puede tener solo un capítulo, un programa completo puede consistir en solo uno
unidad de programa, que se conoce como programa principal. En su forma más simple, consiste en una serie
de declaraciones de los tipos con los que hemos estado tratando hasta ahora, y termina con un final
declaración, que actúa como una señal para que la computadora deje de procesar el programa actual.
Para probar si una unidad de programa de este tipo funciona correctamente, necesitamos poder
salida, a un terminal o impresora, los valores de las cantidades calculadas. Este tema será completamente
explicado en el Capítulo 10, y por el momento solo necesitamos saber que esto se puede lograr
por una declaración de la forma
print *, 'var1 =', var1, 'var2 =', var2
que generará una línea como
var1 = 1.0 var2 = 2.0
Del mismo modo, los datos de entrada se pueden leer mediante declaraciones como
leer *, val1, val2
Esto es suficiente para permitirnos escribir programas simples como el de la Figura 4.8, que genera
los valores convertidos de una escala de temperatura entre los límites especificados y la Figura 4.9, que
construye una lista vinculada. Las entradas de muestra se muestran al final de cada ejemplo.

Página 13
Control construye 65
Figura 4.8 Imprima una tabla de conversión.
!
Imprima una tabla de conversión de Fahrenheit y Celsius
!
escalas de temperatura entre los límites especificados.
!
real
:: celsius, fahrenheit
entero
:: baja_temp, alta_temp, temperatura
personaje :: escala
!
read_loop: do
!
!
Leer escala y límites
lectura *, escala, baja_temp, alta_temp
!
!
Verificar datos válidos
if (scale / = 'C' .and. scale / = 'F') sale de read_loop
!
!
Recorrer los límites
hacer temperatura = baja_temp, alta_temp
!
!
Elija la fórmula de conversión
seleccione caso (escala)
caso ('C')
celsius = temperatura
Fahrenheit = 9.0 / 5.0 * celsius + 32.0
!
Imprimir entrada de tabla
print *, celsius, 'grados C corresponden a',
Y
Fahrenheit, 'grados F'
caso ('F')
Fahrenheit = temperatura
celsius = 5.0 / 9.0 * (fahrenheit-32.0)
!
Imprimir entrada de tabla
print *, fahrenheit, 'grados F corresponden a', &
celsius, 'grados C'
seleccione final
fin hacer
end do read_loop
!
!
Terminación
print *, 'Fin de datos válidos'
fin
C 90
100
F 20
32
*0
00

Página 14
66 Fortran moderno explicado
Figura 4.9 Construcción e impresión de una lista vinculada.
escriba entrada! Tipo para matriz dispersa
real
:: valor
entero
:: índice
tipo (entrada), puntero :: siguiente
entrada de tipo final
tipo (entrada), puntero :: primero, actual
entero
:: llave
real
:: valor
!
! Crear una lista nula
anular (primero)
!
! Llenar la lista
hacer
leer *, clave, valor
si (tecla <= 0) sale
asignar (actual)
actual = entrada (valor, clave, primero)
primero => actual
fin hacer
!
! Imprime la lista
actual => primero
hacer
if (.not.associated (current)) salir
print *,% índice actual,% valor actual
actual => actual% siguiente
fin hacer
fin
14
29
00

Página 15
Construcciones de control 67
Ejercicios
1. Escribe un programa que
a) define una matriz para tener 100 elementos;
b) asigna a los elementos los valores 1,2,3, ..., 100;
c) lee dos valores enteros en el rango de 1 a 100;
d) invierte el orden de los elementos de la matriz en el rango especificado por los dos valores.
2. Los dos primeros términos de la serie de Fibonacci son ambos 1, y todos los términos posteriores se definen como el
suma de los dos términos anteriores. Escriba un programa que lea un límite de valor entero y que
calcula e imprime los valores de los primeros términos límite de la serie.
3. Los coeficientes de órdenes sucesivas de la expansión binomial se muestran en el Pascal normal.
forma triangular como
1
11
121
1331
14641
etc.
Escriba un programa que lea un límite de valor entero e imprima los coeficientes del primer límite
líneas del triángulo de Pascal.
4. Defina una variable de caracteres de longitud 80. Escriba un programa que lea un valor para esta variable.
Suponiendo que cada carácter en la variable es alfabético, escriba código que los clasifique en
ordena alfabéticamente e imprime la frecuencia de aparición de cada letra.
5. Escriba un programa para leer un límite de valor entero e imprima los números primos del primer límite, por cualquier
método.
6. Escriba un programa que lea un valor x y calcule e imprima el valor correspondiente x / (1. + x).
El caso x = -1. debería producir un mensaje de error y ser seguido por un intento de leer un nuevo
valor de x.
7. Dada una cadena de entradas del tipo de entrada de la Sección 2.12, modifique el código en la Figura 4.5
(Sección 4.4) para que elimine la entrada con el índice 10 y haga que la entrada anterior apunte a
La siguiente entrada.

Página 16

Página 17

5. Unidades y procedimientos del programa


5.1 Introducción
Como vimos en el capítulo anterior, es posible escribir un programa completo de Fortran como
unidad individual, pero es preferible dividir el programa en unidades manejables. Cada uno
la unidad de programa corresponde a una tarea de programa que puede entenderse fácilmente e, idealmente, puede
ser escrito, compilado y probado de forma aislada. Discutiremos tres tipos de unidad de programa, la
programa principal, subprograma externo y módulo. Los submódulos evitan los problemas asociados
con módulos muy grandes y se analizan en el Capítulo 16.
Un programa completo debe, como mínimo, incluir un programa principal. Esto puede contener
declaraciones del tipo que hemos conocido hasta ahora en ejemplos, pero normalmente es lo más importante
las declaraciones son invocaciones o llamadas a programas subsidiarios, cada uno de los cuales se conoce como
subprograma Un subprograma define una función o una subrutina. Estos difieren en que un
La función devuelve un solo objeto y generalmente no altera los valores de sus argumentos (de modo que
representa una función en el sentido matemático), mientras que una subrutina generalmente realiza un
tarea más complicada, devolviendo varios resultados a través de sus argumentos y por otros medios.
Las funciones y subrutinas se conocen colectivamente como procedimientos.
Hay varios tipos de subprogramas. Un subprograma puede ser una unidad de programa en sí mismo
derecha, en cuyo caso se llama subprograma externo y define un procedimiento externo.
Los procedimientos externos también pueden definirse por otros medios que no sean Fortran. Un subprograma puede
ser miembro de una colección en una unidad de programa llamada módulo, en cuyo caso lo llamamos
un subprograma de módulo y define un procedimiento de módulo. Se puede colocar un subprograma
dentro de un subprograma de módulo, un subprograma externo o un programa principal, en cuyo caso
lo llama un subprograma interno y define un procedimiento interno. Subprogramas internos
es posible que no estén anidados, es decir, que no contengan más subprogramas, y esperamos que
normalmente son secuencias cortas de código, digamos hasta unas veinte líneas. Ilustramos el anidamiento
de subprogramas en unidades de programa en la Figura 5.1. Si una unidad de programa o subprograma contiene un
subprograma, se llama el host de ese subprograma.
Además de contener una colección de subprogramas, un módulo puede contener definiciones de datos,
definiciones de tipo derivado, bloques de interfaz (Sección 5.11) y grupos de listas de nombres (Sección 8.20).
Esta colección puede proporcionar instalaciones asociadas con alguna tarea en particular, como proporcionar
aritmética matricial, una instalación de biblioteca o una base de datos. A veces puede ser grande.
En este capítulo describiremos las unidades del programa y las declaraciones que están asociadas con
ellos. Dentro de un programa completo pueden aparecer en cualquier orden, pero muchos compiladores requieren
un módulo para preceder a otras unidades de programa que lo usan.
Fortran moderno explicado, 2da edición. Michael Metcalf, John Reid y Malcolm Cohen. prensa de la Universidad de Oxford
(2018) cG Michael Metcalf, John Reid y Malcolm Cohen 2018. DOI 10.1093 / oso / 9780198811893.001.0001

Página 18
70 Fortran moderno explicado
Figura 5.1 Anidamiento de subprogramas en unidades de programa.
5.2 Programa principal
Cada programa completo debe tener uno y solo un programa principal. Opcionalmente, puede
contener llamadas a subprogramas. Un programa principal tiene la siguiente forma:
[nombre-programa-programa]
[especificaciones-stmts]
[ejecutable-stmts]
[contiene
[subprograma interno]. . . ]
fin [programa [nombre-programa]]
La declaración del programa es opcional, pero recomendamos su uso. El nombre del programa puede ser
cualquier nombre válido de Fortran como modelo. La única declaración no opcional es la declaración final,
que tiene dos propósitos. Actúa como una señal para el compilador de que ha llegado al final de
la unidad del programa y, cuando se ejecuta, hace que el programa se detenga. 1 Si incluye programa
nombre, este debe ser el nombre en la declaración del programa. Recomendamos usar el formulario completo
para que sea claro tanto para el lector como para el compilador exactamente lo que termina al final
declaración.
Un programa principal sin llamadas a subprogramas generalmente se usa solo para pruebas cortas, como en
prueba de programa
print *, '¡Hola mundo!'
prueba de programa final
Las instrucciones de especificación definen el entorno para las instrucciones ejecutables. Hasta aquí,
hemos cumplido con la declaración de declaración de tipo (entero, real, complejo, lógico, carácter,
1 Para un programa de matriz (Capítulo 17), la imagen deja de ejecutarse pero sus datos permanecen accesibles para otras imágenes.
Módulo
subprogramas
Módulo
Interno
subprogramas
Principal
programa
Interno
subprogramas
Externo
subprograma
Interno
subprogramas

Página 19
Unidades y procedimientos del programa 71
y tipo (nombre-tipo)) que especifica el tipo y otras propiedades de las entidades que enumera,
y el bloque de definición de tipo (delimitado por el tipo nombre-tipo y las declaraciones de tipo final). Nosotros
cumplirá con otras declaraciones de especificación en este y los próximos dos capítulos.
Las instrucciones ejecutables especifican las acciones que se deben realizar. Hasta ahora nos hemos encontrado
la instrucción de asignación, la instrucción de asignación de puntero, la instrucción if y construcción,
las construcciones do y case, la declaración go to y las declaraciones read e print. Lo haremos
cumplir con otras declaraciones ejecutables en este y en capítulos posteriores. Ejecución de un programa siempre
comienza con la primera instrucción ejecutable del programa principal.
La declaración contiene separa cualquier subprograma interno del cuerpo del principal
programa. Describiremos los subprogramas internos en la Sección 5.6. Están excluidos de
la secuencia de sentencias ejecutables del programa principal; si la última instrucción ejecutable
antes de que se ejecute un contenedor sin bifurcación, la siguiente instrucción ejecutada será la
declaración final Tenga en cuenta que aunque la sintaxis permite una declaración contiene sin ningún
siguiendo los subprogramas internos, no sirve para nada y, por lo tanto, debe evitarse. El fin
La instrucción puede ser el objetivo de una rama de una de las instrucciones ejecutables. Si el final
se ejecuta la instrucción, se detiene la ejecución adicional. 1
5.3 La declaración de stop
Otra forma de detener la ejecución del programa es ejecutar una declaración de detención. Esta declaración puede
aparecer en el programa principal o en cualquier subprograma. Un programa bien diseñado normalmente regresa
control al programa principal para la terminación del programa, por lo que debería aparecer la instrucción stop
ahí. Sin embargo, en aplicaciones donde aparecen varias sentencias stop en varios lugares de
un programa completo, es posible distinguir cuál de las declaraciones de detención ha causado
la terminación agregando a cada uno un código de detención que consiste en un entero predeterminado o predeterminado
expresión constante de caracteres (Secciones 2.6.1 y 2.6.4). Esto podría ser utilizado por un determinado
procesador para indicar el origen de la parada en un mensaje. 2 ejemplos son
detener
parada 12345
parada -2 ** 20
detener 'Datos incompletos. Programa terminado.
stop 'load_data_type_1' // ': valor fuera de rango'
El estándar Fortran requiere que, en caso de terminación, mediante una declaración de detención, si existe alguna IEEE
la excepción de punto flotante es señalización (Capítulo 18), se debe escribir un mensaje de advertencia al error
unidad de archivo error_unit del módulo iso_fortran_env (Sección 9.24.1).
La norma también recomienda que cualquier código de detención se escriba en la misma unidad y, si
es un número entero, que se utilizará como "estado de salida del proceso" si el sistema operativo tiene
concepto. Recomienda además que se proporcione un estado de salida de cero si el código de detención es de
escriba el carácter o el programa termina con una declaración de finalización del programa. Sin embargo, estos
son solo recomendaciones y, en cualquier caso, los sistemas operativos a menudo tienen un rango limitado
para el estado de salida del proceso, por lo que los valores fuera del rango de 0-127 deben evitarse para esto
propósito.
2 Esta declaración se extiende en Fortran 2018, consulte la Sección 23.5.

Página 20
72 Fortran moderno explicado
También hay una declaración de detención de error (Sección 17.14) que se puede usar para el programa
terminación. La principal diferencia entre las declaraciones stop y error stop es que
esto último provoca la terminación del error en lugar de la terminación normal. Tiene el mismo IEEE
requisitos de informes de excepción y código de detención como detención, y la salida de proceso recomendada
El estado con un código de parada numérico es nuevamente el valor del código de parada, pero por lo demás, el estado de
salida
debe ser distinto de cero, de acuerdo con las convenciones típicas del sistema operativo donde cero
indica éxito y no cero indica falla. (Este también es el código de salida recomendado
para otras situaciones de terminación de error, como un error o asignación de entrada / salida no manejada
fracaso.)
Otras diferencias entre terminación normal y error son:
• la terminación normal cierra correctamente todos los archivos, esperando cualquier operación de entrada / salida en
el progreso se completa, pero la terminación del error no tiene dicho requisito (esto podría causar
pérdida de datos si los archivos aún se están escribiendo);
• en un programa de matriz con múltiples imágenes (Capítulo 17), el cómputo completo es
terminado, no solo una sola imagen (Sección 17.14).
Aunque los valores de código de salida de terminación normal y de error son meramente recomendables
A diferencia del estándar Fortran, rara vez tiene sentido cuestionar las opciones del procesador.
aquí. Por estas razones, recomendamos el uso de un mensaje informativo en lugar de un
entero para las declaraciones stop y error stop.
5.4 Subprogramas externos
Los subprogramas externos se llaman desde un programa principal o desde otro lugar, generalmente para realizar un
tarea bien definida en el marco de un programa completo. Aparte de los principales
declaración, tienen una forma muy parecida a la de un programa principal:
subrutina-stmt
[especificaciones-stmts]
[ejecutable-stmts]
[contiene
[subprograma interno]. . . ]
end [subrutina [nombre-subrutina]]
o
función-stmt
[especificaciones-stmts]
[ejecutable-stmts]
[contiene
[subprograma interno]. . . ]
end [function [nombre-función]]
La declaración contiene juega exactamente el mismo papel que dentro de un programa principal (ver
Sección 5.2). Como antes, aunque la sintaxis permite una declaración contiene sin ninguna
siguiendo los subprogramas internos, no recomendamos hacerlo. El efecto de ejecutar un
La declaración final en un subprograma es devolver el control a la persona que llama, en lugar de detener la ejecución.

Página 21
Unidades y procedimientos del programa 73
En cuanto a la declaración final del programa, recomendamos utilizar el formulario completo para la declaración final
para que sea claro tanto para el lector como para el compilador exactamente lo que termina.
La forma más simple de subprograma externo define una subrutina sin ningún argumento y
tiene una subrutina-stmt de la forma
subrutina nombre-subrutina
Tal subprograma es útil cuando un programa consiste en una secuencia de fases distintas, en
en cuyo caso el programa principal consiste en una secuencia de declaraciones de llamada que invocan
subrutinas como en el ejemplo
programa de juego
! Programa principal para controlar un juego de cartas
llamada aleatoria
! Primero baraja las cartas.
trato de llamada
! Ahora trata con ellos.
llamada play
! Jugar el juego.
pantalla de llamada
! Muestra el resultado.
final del juego del programa
! Cese de ejecución.
Pero, ¿cómo manejamos el flujo de información entre las subrutinas? Como juega
¿Sabes qué cartas ha repartido? De hecho, hay dos métodos por los cuales la información
puede ser aprobado El primero es a través de los datos contenidos en un módulo (Sección 5.5) y al que accede el
subprogramas, y el segundo es a través de argumentos (Sección 5.7) en las llamadas al procedimiento.
5.5 Módulos
El tercer tipo de unidad de programa, el módulo, proporciona un medio de empaquetar datos globales,
tipos derivados y sus operaciones asociadas, subprogramas, bloques de interfaz (Sección 5.11),
y grupos de listas de nombres (Sección 8.20). Todo lo relacionado con alguna tarea (como intervalo
aritmética, ver más adelante en esta sección) se puede recopilar en un módulo y acceder siempre
es necesario. Aquellas partes que están asociadas con el funcionamiento interno y que no son de interés.
para el usuario puede hacerse 'invisible' para el usuario, lo que permite alterar el diseño interno
sin la necesidad de alterar el programa que lo usa y evita la alteración accidental de
datos. Las bibliotecas de Fortran a menudo consisten en conjuntos de módulos.
El módulo tiene la forma
módulo nombre-módulo
[especificaciones-stmts]
[contiene
[subprograma de módulo]. . . ]
fin [módulo [nombre-módulo]]
En cuanto a otras unidades de programa, aunque la sintaxis permite una declaración contiene sin ninguna
siguiendo los subprogramas del módulo, no recomendamos hacerlo. En cuanto al programa final,
subrutina final y declaraciones de función final, recomendamos utilizar el formulario completo para
declaración final
En su forma más simple, el cuerpo consta solo de especificaciones de datos. Por ejemplo
estado del módulo
entero, dimensión (52) :: tarjetas
estado del módulo final

Página 22
74 Fortran moderno explicado
podría mantener el estado de juego del juego de la Sección 5.4. Se accede por la declaración
estado de uso
apareciendo al comienzo del juego del programa principal y los subprogramas barajan, reparten,
jugar y exhibir. Las tarjetas de matriz se configuran aleatoriamente para contener los valores enteros 1 a 52
en un orden aleatorio, donde cada valor entero corresponde a una tarjeta de juego predefinida. por
Por ejemplo, 1 podría representar el as de los clubes, 2 para los dos clubes, etc., hasta 52 para el rey de
espadas. El juego de subrutinas cambia las cartas de matriz y finalmente se accede a ellas
por pantalla de subrutina.
Otro ejemplo de datos globales en un módulo serían las definiciones de los valores de
parámetros de tipo amable (Sección 2.6) que pueden ser necesarios en todo un programa. Ellos pueden
colocarse en un módulo y usarse donde sea necesario. En un procesador que sea compatible con todos
los tipos enumerados, un ejemplo podría ser:
módulo numeric_kinds
! constantes con nombre para enteros de 4, 2 y 1 byte:
entero, parámetro ::
Y
i4b = selected_int_kind (9),
Y
i2b = selected_int_kind (4),
Y
i1b = selected_int_kind (2)
! y para reales de precisión simples, dobles y cuádruples:
entero, parámetro ::
Y
sp = kind (1.0),
Y
dp = selected_real_kind (2 * precisión (1.0_sp)), y
qp = selected_real_kind (2 * precisión (1.0_dp))
módulo final numeric_kinds
Una función muy útil para los módulos es contener definiciones de tipos y sus asociados.
operadores Por ejemplo, un módulo puede contener el intervalo de tipo de la Sección 3.9, como se muestra
en la figura 5.2. Dado este módulo, cualquier unidad de programa que necesite este tipo y sus operadores necesitan
solo incluya la declaración
usar intervalo_aritmético
a la cabeza de sus declaraciones de especificación.
Un subprograma de módulo tiene exactamente la misma forma que un subprograma externo. Tiene acceso
a otras entidades del módulo, incluida la capacidad de llamar a otros subprogramas del módulo,
más bien como si contuviera una declaración de uso para su módulo.
Un módulo puede contener declaraciones de uso que acceden a otros módulos. No debe acceder a sí mismo
directa o indirectamente a través de una cadena de declaraciones de uso, por ejemplo, a acceder a b y b
accediendo a. El estándar no requiere ordenar los módulos, pero la práctica normal es
requiere que cada módulo preceda a su uso. Recomendamos esta práctica, que es requerida por
Muchos compiladores.
Es posible dentro de un módulo especificar que algunas de las entidades son privadas y no pueden
Se accede desde otras unidades del programa. Además, hay formas de la declaración de uso que permiten
acceso a solo parte de un módulo y formularios que permiten cambiar el nombre de las entidades a las que se
accede. Estas
Las características se explicarán en las Secciones 8.6.1 y 8.14. Por el momento, suponemos que el
Se accede a todo el módulo sin cambiar el nombre de las entidades.

Página 23
Unidades y procedimientos del programa 75
Figura 5.2 Un módulo para la aritmética de intervalos.
módulo intervalo_aritmético
intervalo de tipo
real :: inferior, superior
intervalo de tipo final
operador de interfaz (+)
procedimiento de módulo add_intervals
interfaz final
...
contiene
función add_intervals (a, b)
tipo (intervalo)
:: add_intervals
tipo (intervalo), intento (in) :: a, b
add_intervals% lower = a% lower + b% lower
add_intervals% upper = a% upper + b% upper
función final add_intervals
...
módulo final intervalo_aritmético
5.6 Subprogramas internos
Hemos visto que los subprogramas internos pueden definirse dentro de los programas principales y externos
subprogramas, y dentro de subprogramas de módulo. Tienen la forma
subrutina-stmt
[especificaciones-stmts]
[ejecutable-stmts]
end [subrutina [nombre-subrutina]]
o
función-stmt
[especificaciones-stmts]
[ejecutable-stmts]
end [function [nombre-función]]
es decir, la misma forma que un subprograma de módulo, excepto que pueden no contener más
subprogramas internos Un subprograma interno tiene acceso automáticamente a todos los hosts
entidades, incluida la capacidad de llamar a sus otros subprogramas internos. Subprogramas internos
debe estar precedido por una declaración contiene en el host. En cuanto a otras declaraciones finales, nosotros
Se recomienda utilizar la forma completa de la declaración final para subprogramas internos.
En el resto de este capítulo describimos varias propiedades de subprogramas que se aplican a
subprogramas externos, módulos e internos. Por lo tanto, no necesitamos describir internamente
subprogramas por separado. Un ejemplo se da en la Figura 5.12 (Sección 5.15).

Página 24
76 Fortran moderno explicado
5.7 Argumentos de procedimientos
Los argumentos de procedimiento proporcionan un medio alternativo para que dos unidades de programa accedan al
mismo
datos. Volviendo a nuestro ejemplo de juego de cartas, en lugar de colocar las tarjetas de matriz en un módulo, nosotros
podría declararlo en el programa principal y pasarlo como un argumento real a cada subprograma,
como se muestra en la Figura 5.3.
Figura 5.3 Llamadas de subrutina con argumentos reales.
programa de juego
! Programa principal para controlar un juego de cartas
entero, dimensión (52) :: tarjetas
Call Shuffle (tarjetas)
! Primero baraja las cartas.
oferta de llamadas (tarjetas)
! Ahora trata con ellos.
call play (cartas)
! Jugar el juego.
pantalla de llamada (tarjetas)
! Muestra el resultado.
final del juego del programa
! Cese de ejecución.
Cada subrutina recibe cartas como argumento ficticio. Por ejemplo, shuffle tiene el
formulario que se muestra en la Figura 5.4.
Figura 5.4 Una subrutina con un argumento ficticio.
subrutina barajar (cartas)
! Subrutina que coloca los valores del 1 al 52 en tarjetas
! En orden aleatorio.
entero, dimensión (52) :: tarjetas
! Declaraciones que llenan tarjetas
...
fin de subrutina barajar
! Regrese a la persona que llama.
Podemos, por supuesto, imaginar un juego de cartas en el que el reparto va a repartir solo tres cartas
a cada uno de los cuatro jugadores. En este caso, sería una pérdida de tiempo para el barajado preparar un
mazo de 52 cartas cuando solo se necesitan las primeras 12 cartas. Esto se puede lograr solicitando
barajar para limitarse a una cantidad de tarjetas que se transmiten en la secuencia de llamada de esta manera:
Call Shuffle (3 * 4, tarjetas (1:12))
Dentro de la combinación aleatoria, definiríamos la matriz para que tenga la longitud dada y el algoritmo para llenar
las tarjetas se colocarían en una construcción do con este número de iteraciones, como se ve en la Figura 5.5.
Hemos visto cómo es posible pasar una matriz y una expresión constante entre dos
Unidades de programa. Un argumento real puede ser cualquier variable o expresión (o un procedimiento
nombre, ver Sección 5.12). Cada argumento ficticio del procedimiento llamado debe estar de acuerdo con
el argumento real correspondiente en tipo, parámetros de tipo y forma. 3 Sin embargo, los nombres
No tiene que ser lo mismo. Por ejemplo, si se hubieran necesitado dos mazos, podríamos tener
escrito el código así:
3 Los requisitos sobre la longitud del personaje y el acuerdo de forma se relajan en la Sección 19.5.
Página 25
Unidades y procedimientos del programa 77
Figura 5.5 Una subrutina con dos argumentos ficticios.
barajar subrutina (tarjetas, tarjetas)
entero
:: tarjetas postales, icard
entero, dimensión (ncards) :: tarjetas
do icard = 1, ncards
...
tarjetas (icard) = ...
fin hacer
fin de subrutina barajar
programa de juego
entero, dimensión (52) :: acards, bcards
llamada aleatoria (tarjetas)
! Primero baraja el mazo.
llamada aleatoria (tarjetas)
! Luego baraja el mazo b.
...
final del juego del programa
El punto importante es que los subprogramas se pueden escribir independientemente uno del otro, el
asociación de los argumentos ficticios con los argumentos reales que ocurren cada vez que la llamada
es ejecutado. Esto se conoce como asociación de argumentos. Podemos imaginar que se use barajar
en otros programas que usan otros nombres. De esta manera, las bibliotecas de subprogramas pueden ser
acumulado
Ser capaz de tener diferentes nombres para argumentos reales y ficticios proporciona útiles
flexibilidad, pero solo debe usarse cuando sea realmente necesario. Cuando el mismo nombre puede ser
usado, el código es más legible.
Como el tipo de argumento real y su argumento ficticio correspondiente deben coincidir, tenga cuidado
debe tomarse cuando se usa la selección de componentes dentro de un argumento real. Por lo tanto, suponiendo
el punto de definición de tipo derivado y el triángulo de la Figura 2.1 (Sección 2.9) están disponibles en
un módulo def, podríamos escribir
usar def
tipo (triángulo) :: t
...
llamada sub (t% a)
...
contiene
subrutina sub (p)
tipo (punto) :: p
...
Un argumento ficticio de un procedimiento puede usarse como un argumento real en un procedimiento
llamada. El procedimiento llamado puede usar su argumento ficticio como argumento real en otro.
78 Fortran moderno explicado
llamada al procedimiento Se construye una cadena con asociación de argumentos en cada enlace. La cadena termina
en un objeto que no es un argumento ficticio, que se conoce como el argumento final de la
argumento ficticio original.
5.7.1 Conjuntos de formas asumidas
Fuera del Apéndice B, requerimos que las formas de los argumentos reales y ficticios estén de acuerdo, y
hasta ahora hemos logrado esto pasando las extensiones de los argumentos de la matriz como adicionales
argumentos Sin embargo, es posible requerir que se tome la forma de la matriz ficticia
automáticamente para ser el del argumento de matriz real correspondiente. Tal matriz se dice
ser una matriz de forma asumida. Cuando la cláusula de dimensión declara la forma, cada
dimensión tiene la forma
[límite inferior] :
donde el límite inferior es una expresión entera que puede depender de los datos del módulo u otro
argumentos (ver la Sección 8.18 para las reglas exactas). Si se omite el límite inferior, el valor predeterminado
es uno. Tenga en cuenta que se pasa la forma y no los límites superior e inferior. por
ejemplo, si la matriz real es a, declarada así:
real, dimensión (0:10, 0:20) :: a
y la matriz ficticia es da, declarada así:
real, dimensión (:, :) :: da
entonces a (i, j) corresponde a da (i + 1, j + 1); para obtener la correspondencia natural, la menor
obligado debe declararse:
real, dimensión (0 :, 0 :) :: da
Para que el compilador sepa que se debe proporcionar información adicional, la interfaz
debe ser explícito (Sección 5.11) en el punto de la llamada. Una matriz ficticia con el puntero o
El atributo asignable no se considera una matriz de forma supuesta porque su forma no es
necesariamente asumido.
5.7.2 Argumentos de puntero
Se permite que un argumento ficticio tenga el puntero de atributo. En este caso, el actual
El argumento también debe tener el puntero de atributo. Cuando se invoca el subprograma, el rango
del argumento real debe coincidir con el argumento ficticio y su asociación de puntero
el estado se pasa al argumento ficticio. Al regresar, el argumento real normalmente toma su
estado de asociación del puntero del del argumento ficticio, pero se vuelve indefinido si
el argumento ficticio está asociado con un objetivo que queda indefinido cuando el retorno es
ejecutado (por ejemplo, si el destino es una variable local que no tiene el atributo guardar,
Sección 8.10).
En el caso de un módulo o procedimiento interno, el compilador sabe cuándo
El argumento es un puntero. En el caso de un procedimiento externo o ficticio, el compilador asume
que el argumento ficticio no es un puntero a menos que se indique lo contrario en un bloque de interfaz
(Sección 5.11).

Página 2
Unidades y procedimientos del programa 79
..
..
También se permite que un argumento real de puntero se corresponda con un ficticio sin puntero
argumento. En este caso, el puntero debe tener un objetivo y el objetivo está asociado con el
argumento ficticio, como en
real, puntero :: a (:, :)
.
asignar (a (80,80))
llamar a buscar (a)
.
subrutina encontrar (c)
real :: c (:, :)! Matriz de forma asumida
El término argumento efectivo se usa para referirse a la entidad que está asociada con un objeto ficticio.
argumento, es decir, el argumento real si no es un puntero, y su objetivo de lo contrario.
5.7.3 Restricciones sobre argumentos reales
Existen dos restricciones importantes sobre los argumentos reales, que están diseñados para permitir
compilador para optimizar en el supuesto de que los argumentos ficticios son distintos de cada
otras y de otras entidades que son accesibles dentro del procedimiento. Por ejemplo, un compilador
puede organizar que una matriz se copie en una variable local en la entrada y se vuelva a copiar en el retorno.
Mientras que un argumento real está asociado con un argumento ficticio, las siguientes declaraciones
sostener:
i) Acción que afecta el estado de asignación o el estado de asociación del puntero del argumento o
cualquier parte del mismo (cualquier asignación de puntero, asignación, desasignación o anulación) debe
ser llevado a través del argumento ficticio. Si esto se hace, entonces durante la ejecución
del procedimiento, el argumento puede ser referenciado solo a través del argumento ficticio.
ii) La acción que afecta el valor del argumento o cualquier parte del mismo debe tomarse a través del
argumento ficticio a menos que
a) el argumento ficticio tiene el atributo puntero;
b) la parte es todo o parte de un subobjeto puntero; o
c) el argumento ficticio tiene el atributo objetivo, el argumento ficticio no
tener intención en (Sección 5.9), el argumento ficticio es escalar o una forma asumida
matriz (Sección 5.7.1), y el argumento real es un objetivo distinto de una matriz
sección con un subíndice vectorial.
Si el valor del argumento o cualquier parte del mismo se ve afectado a través de un argumento ficticio para
que ni a), b) ni c) tienen, entonces durante la ejecución del procedimiento, el
Se puede hacer referencia al argumento solo a través de ese argumento ficticio.
Un ejemplo de i) es un puntero que está anulado (Sección 3.14) mientras aún está asociado con el
argumento ficticio Como ejemplo de ii), considere
llamada modificar (a (1: 5), a (3: 9))

Página 3
80 Fortran moderno explicado
Aquí, un (3: 5) no se puede cambiar a través de ningún argumento ficticio ya que esto violaría
La regla para el otro argumento. Sin embargo, un (1: 2) puede cambiarse a través del primer argumento
y a (6: 9) se puede cambiar a través del segundo. Otro ejemplo es un argumento real.
es un objeto al que se accede desde un módulo; aquí, no se debe acceder al mismo objeto
del módulo por el procedimiento y redefinido. Como tercer ejemplo, supongamos que un interno
la llamada al procedimiento asocia una variable de host h con un argumento ficticio d. Si d se define durante
la llamada, entonces en ningún momento durante la llamada puede ser referenciada directamente.
5.7.4 Argumentos con el atributo objetivo
En la mayoría de los casos, una implementación puede hacer una copia de un argumento real
al ingresar a un procedimiento y copiarlo nuevamente al regresar. Esto puede ser deseable en eficiencia
motivos, particularmente cuando el argumento real no se mantiene en un almacenamiento contiguo. En todo caso,
Si un argumento ficticio no tiene el atributo target ni puntero, cualquier puntero asociado
con el argumento real no se asocien con el argumento ficticio correspondiente
pero permanece asociado con el argumento real.
Sin embargo, la copia de copia no se permite cuando
i) un argumento ficticio tiene el atributo target y es escalar o se supone
matriz en forma; y
ii) el argumento real es un objetivo distinto de una sección de matriz con un subíndice vectorial.
En este caso, los argumentos ficticios y reales deben tener la misma forma, cualquier puntero
asociado con el argumento real se asocia con el argumento ficticio en
invocación, y cualquier puntero asociado con el argumento ficticio en el retorno permanece
asociado con el argumento real.
Cuando un argumento ficticio tiene el atributo objetivo, pero el argumento real no es un objetivo
o es una sección de matriz con un subíndice vectorial, cualquier puntero asociado con el argumento ficticio
obviamente se vuelve indefinido al regreso.
En otros casos donde el argumento ficticio tiene el atributo de destino, ya sea copiado en copia-
La salida depende del procesador. No se debe confiar en las asociaciones de punteros
con tal argumento después de la invocación.
5.8 La declaración de devolución
Vimos en la Sección 5.2 que si se ejecuta la declaración final de un programa principal, más
la ejecución se detiene. Del mismo modo, si se ejecuta la declaración final en un subprograma, el control devuelve
hasta el punto de invocación. Así como la instrucción stop es una instrucción ejecutable que proporciona
un medio alternativo para detener la ejecución, por lo que la instrucción return proporciona una alternativa
medios de devolver el control de un subprograma. Tiene la forma
regreso
y no debe aparecer en un programa principal.

Página 4
Unidades y procedimientos del programa 81
5.9 Intención de argumento
En la Figura 5.5, las tarjetas de argumento ficticio se usaron para pasar información de la barajadura
y el argumento ficticio ncards se utilizó para pasar información; una tercera posibilidad es para un
argumento ficticio que se utilizará para las variables de entrada y salida. Podemos especificar tal intención
en la declaración de declaración de tipo para el argumento, por ejemplo:
barajar subrutina (tarjetas, tarjetas)
entero, intento (in)
:: ncards
entero, intento (fuera), dimensión (ncards) :: tarjetas
Para los argumentos de entrada / salida, se puede especificar la intención inout.
Si se especifica un argumento ficticio con intención, no se debe redefinir (ni ninguna de sus partes)
por el procedimiento, digamos apareciendo en el lado izquierdo de una tarea o aprobándose
como argumento real a un procedimiento que lo redefine. Para la intención de especificación inout,
el argumento real correspondiente debe ser una variable porque la expectativa es que lo hará
ser redefinido por el procedimiento. Para la intención de especificación, el correspondiente real
el argumento debe ser nuevamente una variable; en este caso, la intención es que se use solo para
pasar información, de modo que quede indefinida al ingresar al procedimiento, aparte de cualquier
componentes con inicialización predeterminada (Sección 8.5.5).
Si una función especifica un operador definido (Sección 3.9), los argumentos ficticios deben tener
intento de entrada. Si una subrutina especifica una asignación definida (Sección 3.10), el primer argumento debe
tener intención fuera o dentro, y el segundo argumento debe tener intención dentro.
Si un argumento ficticio no tiene intención, el argumento real puede ser una variable o una expresión,
pero el argumento real debe ser una variable si el argumento ficticio se redefine. En este contexto
notamos que una variable de argumento real, digamos x, se transforma en una expresión si es
encerrado entre paréntesis, (x); su valor se pasa y no se puede redefinir. El compilador
necesitará hacer una copia si la variable x se puede cambiar durante la ejecución del procedimiento,
por ejemplo, si x no es una variable local o es accesible a través de un puntero. Recomendamos que todos los ficticios
Los argumentos deben tener una intención declarada, lo que permite a los compiladores realizar más comprobaciones en
la compilación
tiempo y como buena documentación.
Si un argumento ficticio tiene el atributo puntero, cualquier intento se refiere a su asociación de puntero
(y no al valor del objetivo); es decir, se refiere al descriptor. Un puntero de intención
tiene un estado de asociación indefinido al ingresar al procedimiento; una intención en puntero no puede ser
anulado o asociado durante la ejecución del procedimiento; y el argumento real para un
El puntero de entrada debe ser una variable de puntero (es decir, no puede ser una referencia a un puntero)
función valorada).
Tenga en cuenta que, aunque un intento en puntero no puede cambiar su estado de asociación de puntero
dentro del procedimiento, si está asociado con un objetivo, el valor de su objetivo puede cambiarse.
Por ejemplo,
subrutina maybe_clear (p)
real, puntero, intento (in) :: p (:)
si (asociado (p)) p = 0.0
subrutina final maybe_clear
Del mismo modo, si un argumento ficticio es de un tipo derivado con un componente puntero, su intención
El atributo se refiere al estado de asociación del puntero de ese componente (y no al destino

Página 5
82 Fortran moderno explicado
del componente). Por ejemplo, si la intención está dentro, no hay asignación de puntero, asignación o
Se permite la desasignación.
5.10 Funciones
Las funciones son similares a las subrutinas en muchos aspectos, pero se invocan dentro de un
expresión y devolver un valor que se utiliza dentro de la expresión. Por ejemplo, el subprograma
en la figura 5.6 devuelve la distancia entre dos puntos en el espacio; la declaración
if (distancia (a, c)> distancia (b, c)) entonces
invoca la función dos veces en la expresión lógica que contiene.
Figura 5.6 Una función que devuelve la distancia entre dos puntos en el espacio. Lo intrínseco
La función sqrt se define en la Sección 9.4.
distancia de función (p, q)
real
:: distancia
real, intento (in), dimensión (3) :: p, q
distancia = sqrt ((p (1) -q (1)) ** 2 + (p (2) -q (2)) ** 2 +
Y
(p (3) -q (3)) ** 2)
distancia de función final
Tenga en cuenta la declaración de tipo para el resultado de la función. El resultado se comporta como un maniquí
argumento con intención. Inicialmente no está definido, pero una vez definido, puede aparecer en un
expresión y puede ser redefinido. El tipo también se puede definir en la declaración de función:
distancia de función real (p, q)
Está permitido escribir funciones que cambien los valores de sus argumentos, modifiquen valores
en módulos, confíe en los datos locales guardados (Sección 8.10) de una invocación previa, o realice
operaciones de entrada / salida. Sin embargo, estos se conocen como efectos secundarios y conflictos con el bien.
práctica de programación Donde se necesiten, se debe usar una subrutina. Es tranquilizador
saber que cuando se llama a una función, nada más sucede "detrás de escena", y puede
Ser muy útil para un compilador optimizador, particularmente para subprogramas internos y de módulos.
Se proporciona un mecanismo formal para evitar los efectos secundarios, pero diferimos su descripción para
Sección 7.8.
El resultado de una función puede ser una matriz, en cuyo caso debe declararse como tal.
El resultado de una función también puede ser un puntero. El resultado es inicialmente indefinido. Dentro de
función, debe asociarse o definirse como disociada. Esperamos la función
referencia generalmente para ser tal que se realice una asignación de puntero para el resultado, es decir, el
la referencia se produce como el lado derecho de una asignación de puntero (Sección 3.13), por ejemplo,
real
:: x (100)
real, puntero :: y (:)
...
y => compacto (x)
...

Página 6
Unidades y procedimientos del programa 83
o como un componente puntero de un constructor de estructuras. La referencia también puede aparecer como un
primario de una expresión o como el lado derecho de una asignación ordinaria, en cuyo caso
el resultado debe asociarse con un objetivo definido y el valor del objetivo
es usado Sin embargo, no recomendamos esta práctica, ya que es probable que lleve a la memoria
fuga, discutida al final de la Sección 6.6.
El valor devuelto por una función sin puntero siempre debe definirse.
Además de ser un valor escalar o de matriz de tipo intrínseco, el resultado de una función también puede ser un
valor escalar o de matriz de un tipo derivado, como ya hemos visto en la Sección 3.9. Cuando el
se invoca la función, el valor de la función debe usarse como un todo, es decir, no está permitido
calificarse por selección de subcadena, subíndice de matriz, sección de matriz o componente de estructura.
Aunque esto no es muy útil, se permite que una función tenga una lista de argumentos vacía.
En este caso, los corchetes son obligatorios tanto dentro de la declaración de función como en cada
invocación.
5.10.1 Efectos secundarios prohibidos
Para ayudar a un compilador optimizador, el estándar prohíbe depender de ciertos
efectos Especifica que no es necesario que un procesador evalúe todos los operandos de
una expresión, o para evaluar completamente cada operando, si el valor de la expresión puede ser
determinado de otra manera. Por ejemplo, al evaluar
x> y .or. l (z)! x, y y z son reales; l es una función lógica
no es necesario hacer referencia a la función si x es mayor que y. Dado que algunos procesadores lo harán
realice la llamada y otros no lo harán, ninguna variable (por ejemplo z) que sea redefinida por
La función se considera indefinida después de dicha evaluación de expresión. Del mismo modo, es
no es necesario que un procesador evalúe las expresiones de subíndice o subcadena para una matriz
de tamaño cero u objeto de caracteres de longitud de caracteres cero.
Otra prohibición es que una referencia de función no debe redefinir el valor de una variable
que aparece en la misma declaración o afecta el valor de otra referencia de función en el
misma declaración Por ejemplo, en
d = max (distancia (p, q), distancia (q, r))
se requiere distancia para no redefinir sus argumentos. Esta regla permite cualquier expresión que sea
Los argumentos de una única llamada a procedimiento se evaluarán en cualquier orden. Con respecto a esta regla,
una declaración if,
if (lexpr) stmt
se trata como el equivalente si construye
si (lexpr) entonces
stmt
terminara si
y lo mismo es cierto para la instrucción where (Sección 7.6).
5.11 Interfaces explícitas e implícitas
Una llamada a un subprograma interno debe ser de una declaración dentro de la misma unidad de programa. Eso
se puede suponer que el compilador procesará la unidad de programa en su conjunto y, por lo tanto,

Página 7
84 Fortran moderno explicado
saber todo sobre cualquier subprograma interno. En particular, sabrá sobre su interfaz, es decir,
si define una función o una subrutina, los nombres y propiedades de los argumentos, y
las propiedades del resultado si define una función. Esto, por ejemplo, permite que el compilador
compruebe si los argumentos reales y ficticios coinciden de la forma en que deberían. Decimos
que la interfaz es explícita
Una llamada a un subprograma de módulo debe ser de otra declaración en el módulo o
de una declaración que sigue a una declaración de uso para el módulo. En ambos casos, el compilador
sabemos todo sobre el subprograma, y nuevamente decimos que la interfaz es explícita. Similar,
Los procedimientos intrínsecos (Capítulo 9) siempre tienen interfaces explícitas.
Al compilar una llamada a un procedimiento externo o ficticio (Sección 5.12), el compilador
normalmente no tiene un mecanismo para acceder a su código. Decimos que la interfaz es implícita.
Todo lo que tiene el compilador es la información sobre la interfaz que está implícita en las declaraciones
en el entorno de la invocación, por ejemplo, el número de argumentos y sus tipos.
Para especificar que un nombre es el de un procedimiento externo o ficticio, la instrucción externa es
disponible. Tiene la forma
lista de nombres externos externos
y aparece con otras declaraciones de especificación, después de cualquier uso o declaraciones implícitas
(Sección 8.2) y antes de cualquier declaración ejecutable. El tipo y los parámetros de tipo de un
la función con una interfaz implícita generalmente se especifica mediante una declaración de declaración de tipo para
el nombre de la función; una alternativa es mediante las reglas de tipeo implícito (Sección 8.2) aplicadas a
nombre, pero esto no está disponible en un módulo a menos que la función tenga el atributo privado (ver
Sección 8.6.1).
La declaración externa simplemente especifica que cada nombre externo es el nombre de un
procedimiento externo o ficticio. No especifica la interfaz, que permanece implícita.
Sin embargo, se proporciona un mecanismo para especificar la interfaz. Se puede hacer a través de
un bloque de interfaz del formulario
interfaz
interfaz-cuerpo
interfaz final
Normalmente, el cuerpo de la interfaz es una copia exacta del encabezado del subprograma, las especificaciones
de sus argumentos y resultado de función, y su declaración final. Sin embargo,
• los nombres de los argumentos pueden ser cambiados;
• pueden incluirse otras especificaciones (por ejemplo, para una variable local), pero no internas
procedimientos, declaraciones de datos o declaraciones de formato;
• la información puede ser dada por una combinación diferente de declaraciones; 4 4
• en el caso de un argumento de matriz o resultado de función, las expresiones que especifican un límite
pueden diferir siempre que sus valores nunca puedan diferir; y
4 Una práctica permitida por el estándar, pero que no recomendamos, es que un argumento ficticio sea
declarado implícitamente como un procedimiento invocandolo en una sentencia ejecutable. Si el subprograma tiene un ficticio
procedimiento, la interfaz necesitará una declaración externa para ese procedimiento ficticio.

Página 8
Unidades y procedimientos del programa 85
• un procedimiento recursivo (Secciones 5.16 y 5.17) o un procedimiento puro (Sección 7.8) necesita
no se especificará como tal si no se llama como tal.
Se puede proporcionar un cuerpo de interfaz para una llamada a un procedimiento externo definido por otros medios
que Fortran (generalmente C o lenguaje ensamblador).
Nombrar un procedimiento en una declaración externa o darle un cuerpo de interfaz (haciendo ambas
no está permitido) asegura que se trata de un procedimiento externo o ficticio. Recomendamos fuertemente
la práctica para procedimientos externos, ya que de lo contrario el procesador puede interpretar
el nombre como el de un procedimiento intrínseco. Es necesario para la portabilidad ya que los procesadores son
permitido proporcionar procedimientos intrínsecos adicionales. Nombrar un procedimiento en un externo
La declaración hace que todas las versiones de un procedimiento intrínseco que tenga el mismo nombre no estén
disponibles.
Lo mismo es cierto para darle un cuerpo de interfaz (pero no cuando la interfaz es genérica,
Sección 5.18).
El bloque de interfaz se coloca en una secuencia de instrucciones de especificación y esto es suficiente
para hacer explícita la interfaz. Quizás la forma más conveniente de hacer esto es colocar el
bloque de interfaz entre las declaraciones de especificación de un módulo y luego use el módulo.
Las bibliotecas se pueden escribir como conjuntos de subprogramas externos junto con módulos que contienen
bloques de interfaz para ellos. Esto mantiene los módulos de tamaño modesto. Tenga en cuenta que si un procedimiento
es accesible en una unidad de alcance, su interfaz es explícita o implícita allí. Un externo
El procedimiento puede tener una interfaz explícita en algunas unidades de alcance y una interfaz implícita en
otros.
Los bloques de interfaz también se pueden usar para permitir que los procedimientos se llamen como operadores definidos
(Sección 3.9), como asignaciones definidas (Sección 3.10), o con un solo nombre genérico. Nosotros
por lo tanto, difiera la descripción de la generalidad completa del bloque de interfaz hasta la Sección 5.18,
donde se discute sobrecarga.
Se requiere una interfaz explícita para invocar un procedimiento con un puntero o un objeto ficticio de destino.
argumento o resultado de una función de puntero, y se requiere para varias características útiles que
se reunirá más adelante en este y el próximo capítulo. Es necesario para que el procesador pueda hacer
El enlace apropiado. Incluso cuando no se requiere estrictamente, le da al compilador la oportunidad
para examinar las dependencias de datos y mejorar así la optimización. Las interfaces explícitas también son
deseable debido a la seguridad adicional que brindan. Es sencillo asegurar
que todas las interfaces son explícitas, y recomendamos la práctica.
5.11.1 La declaración de importación
Como hemos visto, un cuerpo de interfaz no accede a su entorno por asociación de host, y
por lo tanto, no puede usar constantes con nombre y tipos derivados definidos allí. En particular
podría ser deseable en un procedimiento de módulo para poder describir un procedimiento ficticio que utiliza
tipos y parámetros de tipo amables definidos en el módulo, pero sin asociación de host esto es
imposible, ya que un módulo no puede 'usar' en sí mismo. Este problema se resuelve con la declaración de importación.
Esta declaración solo se puede utilizar en un cuerpo de interfaz y da acceso a entidades con nombre de
la unidad de alcance que contiene.
Por ejemplo, en la Figura 5.7, el cuerpo de la interfaz no sería válido sin la importación
declaración en negrita, porque no tendría medios para acceder al tipo t o al
wp constante

Página 9
86 Fortran moderno explicado
Figura 5.7 Uso de una declaración de importación para proporcionar una interfaz explícita usando tipos y
constantes definidas en el módulo.
módulo m
entero, parámetro :: wp = kind (0.0d0)
tipo t
...
tipo final t
contiene
aplicar subrutina (diversión, ...)
interfaz
función divertida (f)
importación :: t, wp
tipo (t) :: diversión
real (wp) :: f
función final divertida
interfaz final
aplicar subrutina final
módulo final m
La declaración debe colocarse después de cualquier declaración de uso pero antes de cualquier otra declaración
del cuerpo. Tiene la forma general
importar [[::] lista-nombre-importación]
donde cada nombre de importación es el de una entidad que es accesible en la unidad de alcance que contiene. 5 5
Si una entidad importada se define en la unidad de definición del alcance, debe declararse explícitamente
antes del cuerpo de la interfaz.
Una declaración de importación sin una lista importa todas las entidades de la unidad de alcance que contiene
que no se declaran entidades locales del cuerpo de la interfaz; esto funciona de la misma manera que
asociación normal del huésped.
5.12 Procedimientos como argumentos
Hasta ahora, hemos tomado los argumentos reales de una invocación de procedimiento como variables y
expresiones, pero otra posibilidad es que sean procedimientos. Consideremos el caso
de un subprograma de biblioteca para la minimización de funciones. Necesita recibir la función del usuario,
tal como la subrutina barajada en la Figura 5.5 necesita recibir el número requerido de tarjetas.
El código de minimización podría parecerse al código de la Figura 5.8. Observe la forma en que el procedimiento
El argumento es declarado por un bloque de interfaz que juega un papel similar al de la declaración de tipo
declaración para un objeto de datos.
Así como el tipo y la forma de los objetos de datos reales y ficticios deben coincidir, también debe
propiedades de los procedimientos reales y ficticios. El acuerdo es exactamente como para un procedimiento
5 Esta declaración se extiende en Fortran 2018, consulte la Sección 23.11.

Página 10
Unidades y procedimientos del programa 87
y un cuerpo de interfaz para ese procedimiento (ver Sección 5.11). No tendría sentido especificar
un atributo de intención (Sección 5.9) para un procedimiento ficticio, y esto no está permitido.
Figura 5.8 Un subprograma de biblioteca para la minimización de funciones.
Función real mínima (a, b, func)! Devuelve el mínimo
! valor de la función func (x) en el intervalo (a, b)
real, intento (en) :: a, b
interfaz
función real func (x)
real, intento (in) :: x
función de función final
interfaz final
real :: f, x
...
f = func (x)
! invocación de la función del usuario.
...
función final mínima
Figura 5.9 Invocando el código de la biblioteca de la Figura 5.8.
código de módulo
contiene
función real divertida (x)
real, intento (in) :: x
...
función final divertida
código del módulo final
programa principal
usar código
real :: f
...
f = mínimo (1.0, 2.0, diversión)
...
final del programa principal
En el lado del usuario, el código puede verse así en la Figura 5.9. Note que la estructura
es más bien como un sandwich: el código escrito por el usuario invoca el código de minimización que a su vez
invoca el código escrito por el usuario. Un procedimiento externo aquí requeriría la presencia de
un bloque de interfaz y una referencia a una interfaz abstracta (Sección 14.1) o, como mínimo,
el nombre del procedimiento debería declararse en una declaración externa.

Página 11
88 Fortran moderno explicado
El procedimiento que se pasa puede ser un procedimiento externo, interno o de módulo, o un
puntero de procedimiento asociado (Sección 14.2). El argumento real puede ser un procedimiento genérico.
nombre (Sección 5.18); si también es un nombre específico, solo se pasa el procedimiento específico.
Cuando se pasa un procedimiento interno como argumento real, el entorno del host
El procedimiento se pasa con él. Es decir, cuando se invoca a través del maniquí correspondiente
argumento, tiene acceso a las variables del procedimiento de host como si se hubiera invocado allí.
Por ejemplo, en la Figura 5.10, las invocaciones de la función fun from integral utilizarán
valores para las variables freq y alpha del procedimiento del host.
Figura 5.10 Cuadratura usando procedimientos internos.
subrutina s (frecuencia, alfa, inferior, superior, ...)
real (wp), intent (in) :: freq, alpha, lower, upper
...
z = integrar (divertido, inferior, superior)
...
contiene
función real (wp) diversión (x)
real (wp), intento (in) :: x
diversión = x * sin (frecuencia * x) / sqrt (1-alfa * x ** 2)
función final
subrutina final
Si el procedimiento de host es recursivo (Secciones 5.16 y 5.17), la instancia que llamó
El procedimiento con su procedimiento interno como argumento real se conoce como la instancia de host
del procedimiento interno. Son los datos en esta instancia a los que puede acceder el interno
procedimiento.
Además de la conveniencia, este código puede, en principio, ser parte segura de un subproceso múltiple
programa porque los datos para la evaluación de la función no están siendo pasados por variables globales.
5.13 Palabras clave y argumentos opcionales
En aplicaciones prácticas, las listas de argumentos pueden ser largas y las llamadas reales pueden necesitar solo unas
pocas
argumentos Por ejemplo, una subrutina para minimización restringida podría tener la forma
subconjunto mincon (n, f, x, superior, inferior,
Y
igualdades, desigualdades, convexas, xstart)
Para muchas llamadas puede que no haya límites superiores, ni límites inferiores, ni igualdad, o
sin desigualdades, o puede que no se sepa si la función es convexa o sensible
punto de partida puede no ser conocido. Todos los argumentos ficticios correspondientes pueden declararse
opcional (ver también la Sección 8.9). Por ejemplo, los límites pueden ser declarados por la declaración
real, opcional, dimensión (n) :: superior, inferior
Si los primeros cuatro argumentos son los únicos buscados, podemos usar la declaración

Pagina 12
Unidades y procedimientos del programa 89
llamar a mincon (n, f, x, superior)
pero generalmente los argumentos buscados están dispersos. En este caso, podemos seguir un (posiblemente
vacío) lista de argumentos posicionales ordinarios para argumentos iniciales por una lista de argumentos de palabras
clave,
como en la declaración
llamar a mincon (n, f, x, igualdades = q, xstart = x0)
Las palabras clave son los nombres de argumento ficticios y no debe haber más posicionales.
argumentos después del primer argumento de palabra clave.
Este ejemplo también ilustra los méritos de los argumentos posicionales y de palabras clave en cuanto a
la legibilidad se refiere. Una pequeña cantidad de argumentos posicionales principales (por ejemplo, n, f,
yx) se vinculan fácilmente en la mente del lector con los argumentos ficticios correspondientes. Más allá
esto, las palabras clave son muy útiles para el lector al hacer estos enlaces. Recomendamos su
se usa para listas de argumentos largos incluso cuando no hay huecos causados por argumentos opcionales que
No están presentes.
Un argumento no opcional debe aparecer exactamente una vez, ya sea en la lista posicional o en el
lista de palabras clave Un argumento opcional puede aparecer como máximo una vez, ya sea en la lista posicional o
en la lista de palabras clave. Un argumento no debe aparecer en ambas listas.
El subprograma llamado necesita alguna forma de detectar si un argumento está presente para que
puede tomar las medidas apropiadas cuando no lo es. Esto lo proporciona la función intrínseca presente
(Ver Sección 9.2). Por ejemplo
presente (xstart)
devuelve el valor .true. si la llamada actual ha proporcionado un punto de partida y .false.
de otra manera. Cuando está ausente, el subprograma podría, por ejemplo, usar un número aleatorio
generador para proporcionar un punto de partida.
Se produce una ligera complicación si se usa un argumento ficticio opcional dentro del subprograma
como argumento real en una invocación de procedimiento. Por ejemplo, nuestra subrutina de minimización
podría comenzar llamando a una subrutina que maneja el problema de igualdad correspondiente mediante
llamada
llame a mineq (n, f, x, igualdades, convexo, xstart)
En tal caso, un argumento opcional ausente también se considera ausente en el segundo nivel
subprograma Por ejemplo, cuando no hay convexidad en la llamada de mincon, se considera como
ausente en mineq también. Tales argumentos ausentes pueden propagarse a través de cualquier número de llamadas,
siempre que el argumento ficticio sea opcional en cada caso. Un argumento ausente además suministrado
como argumento real debe especificarse como un todo, y no como un subobjeto. Además,
no se permite asociar un puntero ausente con un argumento ficticio sin puntero (el
el objetivo está doblemente ausente).
Dado que el compilador no podrá hacer las asociaciones apropiadas a menos que sepa
las palabras clave (nombres de argumento ficticios), la interfaz debe ser explícita (Sección 5.11) si hay alguna
de los argumentos ficticios son opcionales o se utilizan argumentos de palabras clave. Tenga en cuenta que una interfaz
Se puede proporcionar un bloque para un procedimiento externo para hacer explícita la interfaz. En todos los casos
donde se proporciona un bloque de interfaz, son los nombres de los argumentos ficticios en el bloque
que se usan para resolver las asociaciones.

Página 13
90 Fortran moderno explicado
5.14 Alcance de las etiquetas
La ejecución del programa principal o un subprograma siempre comienza en su primera instrucción ejecutable
y cualquier ramificación siempre tiene lugar desde una de sus declaraciones ejecutables a otra.
De hecho, cada subprograma tiene su propio conjunto independiente de etiquetas. Esto incluye el caso de
Un subprograma de host con varios subprogramas internos. Se puede usar la misma etiqueta en
host y los subprogramas internos sin ambigüedad.
Este es nuestro primer encuentro con el alcance. El alcance de una etiqueta es un programa principal o un
subprograma, excluyendo cualquier subprograma interno que contenga. La etiqueta puede ser utilizada
inequívocamente en cualquier lugar entre las declaraciones ejecutables de su alcance. Tenga en cuenta que el anfitrión
la declaración final puede estar etiquetada y ser un objetivo de rama de una declaración de host; eso es el
Los subprogramas internos dejan un agujero en el alcance del host (ver Figura 5.11).
Figura 5.11 Un ejemplo de ámbitos anidados.
alcance del módulo1
! alcance 1
...
! alcance 1
contiene
! alcance 1
subrutina scope2
! alcance 2
tipo scope3
! alcance 3
...
! alcance 3
tipo final scope3
! alcance 3
interfaz
! alcance 2
...
! alcance 4
interfaz final
! alcance 2
...
! alcance 2
contiene
! alcance 2
función scope5 (...)! alcance 5
...
! alcance 5
función final scope5! alcance 5
subrutina final end2
! alcance 2
módulo final alcance1
! alcance 1
5.15 Alcance de los nombres
En el caso de una entidad nombrada, hay un conjunto similar de declaraciones dentro de las cuales el nombre puede
siempre se utilizará para referirse a la entidad. Aquí, las definiciones de tipo derivado y los bloques de interfaz como
así como los subprogramas pueden hacer agujeros en los ámbitos. Esto nos lleva a considerar cada unidad de programa
como
que consiste en un conjunto de unidades de alcance no superpuestas. Una unidad de alcance es una de las siguientes:
• una definición de tipo derivado;
• un cuerpo de interfaz de procedimiento, excluyendo cualquier definición de tipo derivado y cuerpos de interfaz
contenido dentro de ella; o

Página 14
Unidades y procedimientos del programa 91
• una unidad de programa o subprograma, excluyendo definiciones de tipo derivado, cuerpos de interfaz y
subprogramas contenidos en él.
Un ejemplo que contiene cinco unidades de alcance se muestra en la Figura 5.11.
Una vez que una entidad ha sido declarada en una unidad de alcance, su nombre puede usarse para referirse a ella
en esa unidad de alcance. Una entidad declarada en otra unidad de alcance es siempre una entidad diferente
incluso si tiene el mismo nombre y exactamente las mismas propiedades. 6 Cada uno se conoce como local
entidad. Esto es muy útil para el programador, que no tiene que preocuparse por el
posibilidad de enfrentamientos accidentales de nombres. Tenga en cuenta que esto también es cierto para los tipos
derivados. Incluso si
dos tipos derivados tienen el mismo nombre y los mismos componentes, entidades declaradas con ellos
son tratados como de diferentes tipos. 6 6
Una declaración de uso del formulario
use nombre-módulo
se considera como una redeclaración de todas las entidades del módulo dentro de la unidad de alcance local, con
exactamente los mismos nombres y propiedades. Se dice que las entidades del módulo son accesibles por uso
asociación. Los nombres de entidades en el módulo no se pueden usar para declarar entidades locales (pero
consulte la Sección 8.14 para obtener una descripción de otras instalaciones proporcionadas por la declaración de uso
cuando
Se requiere mayor flexibilidad).
Figura 5.12 Ejemplos de asociación de host.
subrutina exterior
real :: x, y
...
contiene
subrutina interior
real :: y
y = f (x) + 1.! x y f accedido por la asociación de host
...
subrutina final interna
función f (z)
real
:: f
real, intento (in) :: z
...
función final f
subrutina final externa
En el caso de una definición de tipo derivado, un subprograma de módulo o un subprograma interno,
la unidad de alcance que la contiene de inmediato se conoce como la unidad de alcance del host. El nombre
de una entidad en la unidad de alcance del host (incluida una entidad a la que se accede mediante la asociación de uso) es
tratados como redeclarados automáticamente con las mismas propiedades, siempre que ninguna entidad
este nombre se declara localmente, es un argumento ficticio local o resultado de función, o es accedido por
6 Apartedel efecto de la asociación de almacenamiento, que no se analiza hasta el Apéndice A y cuyo uso consideramos
desalentar.

Página 15
92 Fortran moderno explicado
usar asociación. Se dice que la entidad anfitriona es accesible por asociación de host. Por ejemplo, en
En la subrutina interna de la Figura 5.12, x es accesible mediante la asociación del host, pero y es un elemento separado
variable local y la y del host es inaccesible. Notamos que lo interno llama a otro interno
procedimiento que es una función, f; no debe contener una especificación de tipo para esa función, ya que
La interfaz ya es explícita. Dicha especificación, de hecho, declararía una diferente, externa
función de ese nombre. La misma observación se aplica a un procedimiento de módulo que llama a una función en
El mismo módulo.
Tenga en cuenta que el host no tiene acceso a las entidades locales de una subrutina que contiene.
La asociación de host no se extiende a los bloques de la interfaz a menos que una declaración de importación (Sec-
Se utiliza la sección 5.11.1). Esto permite construir un cuerpo de interfaz mecánicamente a partir de
declaraciones de especificación de un procedimiento externo.
Dentro de una unidad de alcance, cada objeto de datos con nombre, procedimiento, tipo derivado, construcción con
nombre,
y el grupo de la lista de nombres (Sección 8.20) debe tener un nombre distinto, con la única excepción de
nombres genéricos de procedimientos (se describirán en la Sección 5.18). Tenga en cuenta que esto significa que
cualquier aparición del nombre de un procedimiento intrínseco en otro rol hace que el intrínseco
procedimiento inaccesible por su nombre (la función de cambio de nombre descrita en la Sección 8.14 permite
un procedimiento intrínseco para acceder desde un módulo y cambiarle el nombre). Dentro de un tipo derivado
definición, cada componente del tipo, cada procedimiento intrínseco al que se hace referencia y cada derivado
tipo o nombre constante al que accede la asociación de host, debe tener un nombre distinto. Aparte de
Estas reglas, los nombres pueden ser reutilizados. Por ejemplo, se puede usar un nombre para los componentes de
dos tipos, o los argumentos de dos procedimientos referenciados con llamadas de palabras clave.
Los nombres de las unidades del programa y los procedimientos externos son globales, es decir, están disponibles en
cualquier lugar.
en un programa completo Cada uno debe ser distinto de los demás y de cualquiera de los locales
entidades de la unidad del programa.
En el otro extremo, la variable do de un do-implícito en una declaración de datos (Sección 8.5.2)
o un constructor de matrices (Sección 7.16) tiene un alcance que es solo el implícito-do. Es diferente
de cualquier otra entidad con el mismo nombre.
5.16 Recurrencia directa
Un subprograma que se invoca, directa o indirectamente a través de una secuencia de otros
invocaciones, se requiere tener la palabra clave recursiva prefijada a su declaración principal. 7 7
Donde el subprograma es una función que se llama a sí misma directamente de esta manera, el nombre de la función
no se puede usar para el resultado de la función y se necesita otro nombre. Esto se hace agregando
una cláusula adicional a la declaración de función como en la Figura 5.13, que ilustra el uso de un
función recursiva para sumar las entradas en una cadena (ver Sección 2.12).
El tipo de la función (y su resultado) puede especificarse en la declaración de la función, ya sea
antes o después del token recursivo:
entero recursivo función factorial (n) resultado (res)
o
resultado entero recursivo factorial (n) resultado (res)
o en una declaración de declaración de tipo para el nombre del resultado (como en la Figura 5.13). De hecho, el resultado
El nombre, en lugar del nombre de la función, debe usarse en cualquier declaración de especificación. En el
7 Este requisito se elimina en Fortran 2018, consulte la Sección 23.14.

Página 16
Unidades y procedimientos del programa 93
Figura 5.13 Sumar las entradas en una lista vinculada.
función recursiva suma (arriba) resultado (s)
tipo (entrada), puntero :: arriba
real
:: s
if (asociado (arriba)) entonces
s = valor% superior + suma (% superior siguiente)
más
s = 0.0
terminara si
suma de funciones finales
declaraciones ejecutables, el nombre de la función se refiere a la función misma y al nombre del resultado
debe usarse para la variable de resultado. Si no hay una cláusula de resultado, se utiliza el nombre de la función
para el resultado, y no está disponible para una llamada de función recursiva.
La cláusula de resultado también se puede usar en una función no recursiva.
Al igual que en la Figura 5.13, cualquier procedimiento recursivo que se llame a sí mismo directamente debe contener un
prueba condicional que termina la secuencia de llamadas en algún momento, de lo contrario llamará
a sí mismo indefinidamente.
Cada vez que se invoca un procedimiento recursivo, se crea un nuevo conjunto de objetos de datos locales,
que deja de existir a la vuelta. Consisten en todos los objetos de datos declarados en el procedimiento
declaraciones de especificación o declaradas implícitamente (ver Sección 8.2), pero exceptuando aquellas con
datos o guardar atributo (ver Secciones 8.5 y 8.10) y cualquier argumento ficticio. La interfaz
es explícito dentro del procedimiento.
Figura 5.14 Código de biblioteca para integración unidimensional.
función recursiva integra (f, límites)
! Integrar f (x) desde los límites (1) a los límites (2)
real :: integrar
interfaz
función f (x)
real
:: f
real, intento (in) :: x
función final f
interfaz final
real, dimension (2), intent (in) :: límites
...
función final integrar

Página 17
94 Fortran moderno explicado
5.17 Recurrencia indirecta
Un procedimiento también puede ser invocado por recursión indirecta, es decir, puede llamarse a sí mismo a través de
llamadas
a otros procedimientos. Para ilustrar que esto puede ser útil, supongamos que deseamos realizar dos
integración dimensional pero solo se muestra el procedimiento para la integración unidimensional
en la figura 5.14. Por ejemplo, suponga que se desea integrar una función f de x e y
sobre un rectángulo Podríamos escribir una función Fortran en un módulo para recibir el valor de x
como argumento y el valor de y desde el módulo en sí por asociación de host, como se muestra en
Figura 5.15. Luego podemos integrar sobre x para un valor particular de y, como se muestra en la Figura 5.16,
donde integrar podría ser como se muestra en la Figura 5.14. Ahora podemos integrarnos sobre el todo
rectángulo así
volumen = integrar (fy, ybounds)
Tenga en cuenta que integrar llamadas fy, que a su vez las llamadas se integran.
Figura 5.15 Una función bidimensional a integrar.
módulo de func
real
:: yval
real, dimensión (2) :: xbounds, ybounds
contiene
función f (xval)
real
:: f
real, intento (in) :: xval
f = ...
! Expresión que involucra xval y yval
función final f
módulo final func
Figura 5.16 Integrar sobre x.
función fy (y)
usar func
real
:: fy
real, intento (in) :: y
yval = y
fy = integrar (f, xbounds)
función final fy
5.18 Sobrecarga e interfaces genéricas
Vimos en la Sección 5.11 cómo usar un bloque de interfaz simple para proporcionar una interfaz explícita
a un procedimiento externo o ficticio. Otro uso es para sobrecargar, que es poder llamar
varios procedimientos por el mismo identificador genérico. Aquí, el bloque de interfaz contiene varios
Los cuerpos de interfaz y la instrucción de interfaz especifican el identificador genérico. Por ejemplo,

Página 18
Unidades del programa y procedimientos 95
El código de la figura 5.17 permite invocar las funciones sgamma y dgamma utilizando
El nombre genérico gamma.
Figura 5.17 Un bloque de interfaz genérico.
interfaz gamma
función sgamma (x)
real (selected_real_kind (6))
:: sgamma
real (selected_real_kind (6)), intento (in) :: x
función final sgamma
función dgamma (x)
real (selected_real_kind (12))
:: dgamma
real (selected_real_kind (12)), intento (in) :: x
función final dgamma
interfaz final
Un nombre específico para un procedimiento puede ser el mismo que su nombre genérico. Por ejemplo, el
El procedimiento sgamma podría renombrarse gamma sin invalidar el bloque de interfaz.
Además, un nombre genérico puede ser el mismo que otro nombre genérico accesible. En
En tal caso, todos los procedimientos que tienen este nombre genérico pueden invocarse a través de él. Esta
la capacidad es importante, ya que un módulo puede necesitar extender las funciones intrínsecas como sin
a un nuevo tipo como intervalo (Sección 3.9).
Si se desea sobrecargar un procedimiento de módulo, la interfaz ya es explícita, por lo que es
inapropiado para especificar un cuerpo de interfaz. En cambio, la declaración
[módulo] procedimiento [::] nombre-procedimiento-lista
se incluye en el bloque de interfaz para nombrar los procedimientos del módulo para sobrecarga; Si
las funciones sgamma y dgamma se definieron en un módulo, el bloque de interfaz se convierte en
interfaz gamma
procedimiento de módulo sgamma, dgamma
interfaz final
Probablemente sea más conveniente colocar dicho bloque en el módulo mismo.
Cualquier especificación genérica en una declaración de interfaz puede repetirse en el correspondiente
declaración de interfaz final ing, por ejemplo,
interfaz gamma final
En cuanto a otras declaraciones finales, recomendamos el uso de este formulario más completo.
Otra forma de sobrecarga ocurre cuando un bloque de interfaz especifica una operación definida
(Sección 3.9) o una asignación definida (Sección 3.10) para extender una operación intrínseca o
asignación. El alcance de la operación o asignación definida es la unidad de alcance que contiene
el bloque de interfaz, pero se puede acceder a él en otro lugar mediante el uso o la asociación de host. Si un intrínseco
El operador se extiende, el número de argumentos debe ser coherente con la forma intrínseca (para
ejemplo, no es posible definir un operador unario *).
La forma general del bloque de interfaz es

Página 19
96 Fortran moderno explicado
interfaz [genérico-espec]
[interfaz-cuerpo]. . .
[[módulo] procedimiento [::] nombre-procedimiento-lista]. . .
! Cuerpos de interfaz y declaraciones de procedimiento de módulo
! Puede aparecer en cualquier orden.
interfaz final [especificación genérica]
donde genérico-espec es uno de
nombre generico
operador (operador definido)
asignación (=)
Se permite una declaración de procedimiento de módulo solo cuando hay una especificación genérica, y todos
los procedimientos deben ser procedimientos de módulo accesibles (como se muestra en el módulo completo en
Figura 5.21 a continuación). Ningún nombre de procedimiento puede recibir una especificación genérica particular más de
Una vez en la interfaz, los bloques son accesibles dentro de una unidad de alcance. Un cuerpo de interfaz debe ser
proporcionado para un procedimiento externo o ficticio.
Si se especifica el operador en la instrucción de interfaz, todos los procedimientos en el bloque deben
ser funciones con uno o dos argumentos no opcionales con intención. Si la asignación es
especificado, todos los procedimientos deben ser subrutinas con dos argumentos no opcionales, el primero
tener intención fuera o dentro y la segunda intención dentro. Para que las invocaciones sean siempre
inequívoco, si dos procedimientos tienen el mismo operador genérico y el mismo número de
argumentos o ambos definen la asignación, uno debe tener un argumento ficticio que corresponda
por posición en la lista de argumentos a un argumento ficticio del otro que tiene un tipo diferente,
parámetro de tipo de tipo diferente o rango diferente.
Todos los procedimientos que tienen un nombre genérico dado deben ser subrutinas o todas deben ser funciones,
incluidos los intrínsecos cuando se extiende un procedimiento intrínseco. Cualquiera de los dos no intrínsecos
los procedimientos con el mismo nombre genérico deben tener argumentos que se puedan distinguir en
ordene que cualquier invocación sea inequívoca. Dos argumentos ficticios son distinguibles si
• uno es un procedimiento y el otro es un objeto de datos,
• ambos son objetos de datos o se sabe que son funciones, pero tienen diferentes tipos, 8 tipos amables
parámetros o rango,
• uno es asignable y el otro es un puntero, o
• una es una función con rango distinto de cero y la otra no se sabe que sea una función.
Las reglas para cualquiera de los dos procedimientos no intrínsecos con el mismo nombre genérico son que
i) uno de ellos tiene un argumento ficticio de objeto de datos no opcional tal que este procedimiento
Número de argumentos ficticios de objeto de datos no opcionales que no son distinguibles
difiere del número del otro procedimiento de tales argumentos ficticios; o
ii) al menos uno de ellos tiene ambos
8 O, si uno o ambos son polimórficos (Sección 15.3), no son compatibles con el tipo.

Página 20
Unidades y procedimientos del programa 97
• un argumento ficticio no opcional que corresponde por posición en el argumento
listar a un argumento ficticio que se puede distinguir de él, o para el que no hay ficticio
argumento corresponde por posición; y
• un argumento ficticio no opcional con el mismo nombre que un argumento ficticio que
es distinguible de él, o para el cual no hay un argumento ficticio de ese nombre.
Estos dos argumentos deben ser los mismos o el argumento que corresponde por
La posición debe aparecer antes en la lista de argumentos ficticios.
Para el caso ii), ambas reglas son necesarias para atender tanto la palabra clave como la posición
listas de argumentos ficticios. Por ejemplo, la interfaz en la Figura 5.18 no es válida porque los dos
las funciones siempre se pueden distinguir en una llamada posicional, pero no en una llamada de palabra clave como
f (i = int, x = posn). Si una invocación genérica es ambigua entre una no intrínseca y una
procedimiento intrínseco, se invoca el procedimiento no intrínseco.
Figura 5.18 Un ejemplo de una regla de sobrecarga rota.
interfaz f! Bloque de interfaz no válido
función fxi (x, i)
real
:: fxi
real, intento (in) :: x
entero
:: yo
función final fxi
función fija (i, x)
real
:: reparar
real, intento (in) :: x
entero
:: yo
corrección de función final
interfaz final
El bloque de interfaz en la Figura 5.19 ilustra la desambiguación basada en el procedimiento: desde
el compilador siempre sabe si un argumento real es un procedimiento, sin referencia a g1
podría ser ambiguo
Figura 5.19 Desambiguación genérica basada en el procedimiento.
interfaz g1
subrutina s1 (a)
un real
subrutina final
subrutina s2 (a)
real, externo :: a
subrutina final
interfaz final
El bloque de interfaz en la Figura 5.20 ilustra la desambiguación en función de si
El argumento es un puntero o asignable: en este caso, el punto de la interfaz es permitir el cambio

Página 21
98 Fortran moderno explicado
entre usar asignable y puntero, sin tener que cambiar el nombre de la desasignación
procedimiento.
Figura 5.20 Desambiguación genérica basada en puntero versus asignable.
interfaz log_deallocate
subrutina log_deallocate_real_pointer_2 (a)
real, puntero, intento (inout) :: a (:, :)
subrutina final
subrutina log_deallocate_real_allocatable_2 (a)
real, asignable, intento (inout) :: a (:, :)
subrutina final
interfaz final
La razón por la que asignable y puntero solo se consideran mutuamente distintivos
posible cuando el puntero no tiene intención es que hay una interacción con el
función de orientación automática (consulte la Sección 7.18.3) que hubiera permitido escribir un
referencia ambigua
Tenga en cuenta que la presencia o ausencia del atributo puntero es insuficiente para garantizar un
invocación inequívoca ya que un argumento real de puntero puede estar asociado con un no puntero
argumento ficticio, ver Sección 5.7.2.
Como ya se mostró, el módulo de palabras clave es opcional; por ejemplo,
interfaz gamma
procedimiento :: sgamma, dgamma
interfaz final
Si se omite el módulo de palabras clave, los procedimientos nombrados no necesitan ser procedimientos de módulo
pero también pueden ser procedimientos externos, procedimientos ficticios o punteros de procedimientos. Cada uno
nombrado
El procedimiento ya debe tener una interfaz explícita para ser utilizado de esta manera. Esto permite, para
ejemplo, un procedimiento externo para aparecer en más de un bloque de interfaz. Por ejemplo,
tipo de cadena de bits
...
tipo final
...
operador de interfaz (*)
función de tipo elemental (cadena de bits) bitwise_and (a, b)
importación :: cadena de bits
tipo (cadena de bits), intento (in) :: a, b
función final bitwise_and
interfaz final
operador de interfaz (.and.)
procedimiento :: bitwise_and
interfaz final
permite el uso de * y .and. operadores para 'bit a bit' y en valores de tipo
cadena de bits

Página 22
Unidades y procedimientos del programa 99
Se permite que un nombre genérico sea el mismo que un nombre de tipo y tiene prioridad sobre
el nombre del tipo; un constructor de estructura para el tipo se interpreta como tal solo si no puede ser
interpretado como una referencia al procedimiento genérico.
Hay muchas aplicaciones científicas en las que es útil controlar los tipos de
cantidades involucradas en un cálculo. Por ejemplo, en el análisis dimensional, mientras que podría
sea sensato dividir la longitud por el tiempo para obtener la velocidad, no es sensato agregar tiempo a la velocidad.
No hay una forma intrínseca de hacer esto, pero concluimos esta sección con un ejemplo de esquema, vea
Figuras 5.21 y 5.22, de cómo podría lograrse usando tipos derivados.
Tenga en cuenta que también se requieren definiciones para operaciones entre entidades similares, como se muestra en
time_plus_time. Del mismo modo, cualquier función intrínseca que pueda ser requerida, aquí sqrt, debe
ser sobrecargado adecuadamente. Por supuesto, esto se puede evitar si los componentes de las variables
se hace referencia directamente, como en
t% segundos = t% segundos + 1.0
5.19 Longitud supuesta de caracteres
Se puede declarar un argumento ficticio de carácter con un asterisco para el valor de la longitud
parámetro de tipo, en cuyo caso toma automáticamente el valor del argumento real. por
ejemplo, una subrutina para ordenar los elementos de una matriz de caracteres podría escribirse así
ordenación de subrutina (n, caracteres)
entero, intento (in)
:: n
carácter (len = *), dimensión (n), intento (in) :: caracteres
...
fin de la subrutina
Si la longitud del argumento real asociado es necesaria dentro del procedimiento, el intrínseco
Se puede invocar la función len (Sección 9.7.1), como en la Figura 5.23.
No se debe usar un asterisco para un valor de parámetro de tipo amable. Esto se debe a un cambio de
la longitud de los caracteres es análoga a un cambio de un tamaño de matriz y puede acomodarse fácilmente en
el código objeto, mientras que un cambio de tipo probablemente requiera una instrucción de máquina diferente
para cada operación que involucra el argumento ficticio. Una versión diferente del procedimiento.
necesitaría generarse para cada valor de tipo posible de cada argumento. La sobrecarga
característica (sección anterior) le da al programador una funcionalidad equivalente con explícito
control sobre qué versiones se generan.
5.20 Las declaraciones de subrutina y función
Terminamos este capítulo dando la sintaxis de la subrutina y las declaraciones de función,
que hasta ahora se han explicado a través de ejemplos. Está
[prefijo] subrutina nombre-subrutina [([lista-argumento-ficticia])]
y
[prefijo] función nombre-función ([lista-argumento ficticio]) [resultado (nombre-resultado)]

Página 23
100 Fortran moderno explicado
Figura 5.21 Un módulo para distinguir entidades reales.
tipo de módulo
tipo de tiempo
real :: segundos
tiempo de finalización
velocidad de tipo
real :: metres_per_second
velocidad de tipo final
longitud de tipo
real :: metros
longitud de tipo final
escriba length_squared
real :: metres_squared
tipo final length_squared
operador de interfaz (/)
procedimiento del módulo length_by_time
interfaz final
operador de interfaz (+)
procedimiento de módulo time_plus_time
interfaz final
interfaz sqrt
procedimiento de módulo sqrt_metres_squared
interfaz final
contiene
función length_by_time (s, t)
tipo (longitud), intento (in) :: s
tipo (tiempo), intento (en)
:: t
tipo (velocidad)
:: length_by_time
length_by_time% metres_per_second = s% metros / t% segundos
función final length_by_time
función time_plus_time (t1, t2)
tipo (tiempo), intento (en)
:: t1, t2
tipo (tiempo)
:: time_plus_time
time_plus_time% segundos = t1% segundos + t2% segundos
función final time_plus_time
función sqrt_metres_squared (l2)
type (length_squared), intent (in) :: l2
tipo (longitud)
:: sqrt_metres_squared
sqrt_metres_squared% meters = sqrt (l2% metres_squared)
función final sqrt_metres_squared
tipo de módulo final

Página 24
Unidades y procedimientos del programa 101
Figura 5.22 Uso del módulo de la Figura 5.21.
prueba de programa
usar clases
tipo (longitud)
:: s = longitud (10.0), l
type (length_squared) :: s2 = length_squared (10.0)
tipo (velocidad)
:: v
tipo (tiempo)
:: t = tiempo (3.0)
v=s/t
! Nota: v = s + t
o
v = s * t sería inválido.
t = t + tiempo (1.0)
l = sqrt (s2)
imprimir *, v, t, l
prueba de programa final
Figura 5.23 Una función con un argumento de longitud de caracteres supuesta.
! Cuente el número de ocurrencias de letra en cadena.
recuento de funciones enteras (letra, cadena)
carácter (1), intención (in) :: letra
carácter (*), intento (in) :: cadena
cuenta = 0
do i = 1, len (cadena)
if (cadena (i: i) == letra) cuenta = cuenta + 1
fin hacer
recuento de funciones finales
donde el prefijo es
prefix-spec [prefix-spec]. . .
y prefix-spec es type, recursive, pure o elemental. No se debe repetir una especificación de prefijo.
Para detalles de tipo, vea la Sección 8.17; esto, por supuesto, no debe estar presente en una subrutina
declaración.
Además de puro y elemental, que se explicará en las Secciones 7.8 y 7.9, cada
La característica se ha explicado por separado y los significados son los mismos en las combinaciones
permitido por la sintaxis.
5.21 Resumen
Un programa consiste en una secuencia de unidades de programa. Debe contener exactamente un programa principal
pero puede contener cualquier número de módulos y subprogramas externos. Hemos descrito cada
tipo de unidad de programa. Los módulos contienen definiciones de datos, definiciones de tipo derivado, lista de nombres
grupos, bloques de interfaz y la declaración de importación, y subprogramas de módulo, todos los cuales
se puede acceder en otras unidades del programa con la declaración de uso. Las unidades del programa pueden ser
en cualquier orden, pero muchos compiladores requieren módulos para preceder su uso.

Página 25
102 Fortran moderno explicado
Los subprogramas definen procedimientos, que pueden ser funciones o subrutinas. También pueden
definirse intrínsecamente (Capítulo 9), y los procedimientos externos pueden definirse por otros medios
que Fortran Hemos explicado cómo se pasa la información entre las unidades del programa y
procedimientos a través de listas de argumentos y mediante el uso de módulos. Se pueden llamar procedimientos
siempre que se especifiquen de forma recursiva.
La interfaz de un procedimiento puede ser explícita o implícita. Si es explícito, las llamadas de palabras clave pueden
ser hecho, y el procedimiento puede tener argumentos opcionales. Los bloques de interfaz permiten procedimientos
para ser invocado como operaciones o asignaciones, o por un nombre genérico. La longitud de los caracteres de
Se pueden suponer argumentos ficticios.
También explicamos el alcance de las etiquetas y los nombres de Fortran, y presentamos
concepto de una unidad de alcance.
Ejercicios
1. Una subrutina recibe como argumentos una matriz de valores, x, y el número de elementos en x, n. Si el
la media y la varianza de los valores en x se estiman por
media =
1
norte
norte


i=1
x (i)
y
varianza =
1
n−1
norte


i=1
(x (i) −medio) 2
escriba una subrutina que devuelva estos valores calculados como argumentos. La subrutina debe verificar
para valores no válidos de n (≤ 1).
2. Una subrutina matrix_mult multiplica dos matrices A y B, cuyas dimensiones son i × j
y j × k, respectivamente, devolviendo el resultado en una matriz C dimensionada i × k. Escribe matrix_mult,
dado que cada elemento de C está definido por
C (m, n) =
j


l=1
(A (m, l) × B (l, n))
Las matrices deberían aparecer como argumentos para matrix_mult.
3. La subrutina random_number (Sección 9.18.3) devuelve un número aleatorio en el rango de 0.0 a 1.0,
es decir
llamar a random_number (r)
! 0≤r <1
Con esta función, escriba la combinación aleatoria de subrutina de la figura 5.4.
4. Una cadena de caracteres consiste en una secuencia de letras. Escribe una función para devolver esa letra del
cadena que aparece más temprano en el alfabeto; por ejemplo, el resultado de aplicar la función a
DGUMVETLOIC es C.
5. Escriba un procedimiento interno para calcular el volumen, πr 2 l, de un cilindro de radio r y longitud l,
utilizando como el valor de π el resultado de acos (-1.0) y referenciarlo en un procedimiento de host.
6. Para un juego de cartas simple de su elección, y utilizando el procedimiento de números aleatorios (Sec.
sección 9.18.3), escriba el reparto y reproducción de subrutinas de la Sección 5.4, utilizando datos en un módulo para
comunicarse entre ellos
Página 1
Unidades y procedimientos del programa 103
7. Los objetos del carácter de tipo intrínseco tienen una longitud fija. Escribir un módulo que contenga una definición.
de un tipo de cadena de caracteres de longitud variable, de longitud máxima 80, y también los procedimientos necesarios
a:
i) asignar una variable de caracteres a una cadena;
ii) asignar una cadena a una variable de caracteres;
iii) devolver la longitud de una cadena;
iv) concatenar dos cadenas.

Página 2

Página 3

6. Asignación de datos.
6.1 Introducción
Existe una suposición subyacente en Fortran de que el procesador proporciona un mecanismo para
Administrar el almacenamiento dinámico. (Un montón es un mecanismo de administración de memoria mediante el cual
el almacenamiento nuevo
puede establecerse y el almacenamiento antiguo puede descartarse en cualquier orden. Mecanismos para tratar
generalmente se requiere la fragmentación progresiva de la memoria.) Las declaraciones descritas
en este capítulo son la interfaz de usuario para ese mecanismo.
6.2 El atributo asignable
Como hemos visto en la Sección 2.10.2, a veces se requiere una matriz solo después de que algunos datos
sido leído o se realizaron algunos cálculos. Para este propósito, un objeto puede recibir
atributo asignable por una declaración como
real, dimensión (:, :), asignable :: a
Su rango se especifica cuando se declara, pero los límites (si es una matriz) no están definidos hasta que
La instrucción de asignación se ha ejecutado para ello. Su estado inicial no está asignado y se convierte en
asignado después de la ejecución exitosa de una instrucción de asignación.
Un ejemplo importante se muestra en la Figura 6.1. El trabajo de matriz se coloca en un módulo y es
asignado al comienzo del programa principal a un tamaño que depende de los datos de entrada. La matriz
luego está disponible durante la ejecución del programa en cualquier subprograma que tenga una declaración de uso
para work_array.
Figura 6.1 Una matriz asignable en un módulo.
módulo work_array
entero
:: n
real, dimension (:,:, :), asignable :: trabajo
módulo final work_array
programa principal
use work_array
leer *, n
asignar (trabajo (n, 2 * n, 3 * n))
...
Fortran moderno explicado, 2da edición. Michael Metcalf, John Reid y Malcolm Cohen. prensa de la Universidad de Oxford
(2018) cG Michael Metcalf, John Reid y Malcolm Cohen 2018. DOI 10.1093 / oso / 9780198811893.001.0001

Página 4
..
..
106 Fortran moderno explicado
Cuando ya no se necesita un objeto asignable a, se puede desasignar mediante la ejecución de
la declaración
desasignar (a)
después de lo cual el objeto no está asignado. La declaración de desasignación se describe en más
detalle en la Sección 6.6.
Si es necesario realizar algún cambio en los límites de una matriz asignable, la matriz debe ser
desasignado y luego asignado de nuevo. Esto puede llevarse a cabo ya sea por desasignación explícita
y reasignación, o automáticamente (ver Sección 6.7). Es un error asignar un asignable
matriz que ya está asignada, o para desasignar una matriz asignable que no está asignada, pero
uno que puede evitarse fácilmente mediante el uso de la función intrínseca asignada (Sección 9.2) para
preguntar sobre el estado de la asignación.
Un estado de asignación indefinido no puede ocurrir. Al regresar de un subprograma, un asignado
el objeto asignable sin el atributo guardar (Sección 8.10) se desasigna automáticamente si
es local al subprograma.
6.3 Parámetros de tipo diferido
Se permite que un valor de parámetro de tipo len sea dos puntos en una declaración de declaración de tipo como
carácter (len = :), puntero :: varchar
para un puntero o una entidad asignable. Indica un parámetro de tipo diferido; tal tipo
el parámetro no tiene un valor definido hasta que se le asigna uno por asignación o asignación de puntero por
ejemplo, en
carácter (:), puntero :: varchar
carácter (100), destino :: nombre
carácter (200), destino :: dirección
.
varchar => nombre
.
varchar => dirección
la longitud de caracteres de varchar después de cada asignación de puntero es la misma que la de su objetivo;
es decir, 100 después de la primera asignación de puntero y 200 después de la segunda.
Para los tipos intrínsecos, solo se puede diferir la longitud de los caracteres. Tipos derivados que son
parametrizado puede tener parámetros de tipo que pueden diferirse, consulte la Sección 13.2.2.
Los parámetros de tipo diferido pueden recibir valores mediante la instrucción de asignación, consulte la Sección 6.5.
Para las variables asignables, también se les pueden dar valores por asignación, consulte la Sección 6.7.
6.4 Escalares asignables
El atributo asignable (y, por lo tanto, la función asignada) también se puede aplicar a escalar
variables y componentes. Esto es particularmente útil cuando se combina con el tipo diferido
parámetros, por ejemplo, en

Página 5
Asignación de datos 107
carácter (:), asignable :: chdata
entero
:: unidad, reclen
...
leer *, reclen
allocate (caracter (reclen) :: chdata)
leer *, chdata
donde reclen permite que se especifique la longitud del carácter en tiempo de ejecución.
6.5 La declaración de asignación
La forma general de la instrucción de asignación es
allocate ([tipo-especificación ::] asignación-lista [, asignación-espec.]...)
donde la lista de asignaciones es una lista de asignaciones del formulario
allocate-object [(matriz-límites-lista)]
cada matriz tiene la forma
[límite inferior:] límite superior
y alloc-spec es uno de
errmsg = erm
molde = expr
fuente = expr
stat = stat
donde ningún especificador puede aparecer más de una vez, stat es una variable entera escalar y erm
es una variable de caracteres escalar predeterminada. Ni stat ni erm pueden ser parte de un objeto siendo
asignado.
La especificación de tipo opcional y los especificadores mold = y source = se analizan en la Sección 15.4.
Si el stat = specifier está presente, stat recibe el valor cero después de un éxito
asignación o un valor positivo después de una asignación fallida (por ejemplo, si es insuficiente
almacenamiento disponible). Después de una ejecución fallida, cada matriz que no fue exitosa
asignado conserva su asignación anterior o el estado de asociación del puntero. Si stat = está ausente y
la asignación no tiene éxito, la ejecución se detiene.
Si el especificador errmsg = está presente y se produce un error durante la asignación, una explicación
El mensaje se asigna a la variable. Por ejemplo,
personaje (200) :: mensaje_error! Probablemente lo suficientemente largo
...
allocate (x (n), stat = allocate_status, errmsg = error_message)
if (allocate_status> 0) entonces
print *, 'Falló la asignación de X:', trim (error_message)
...
! el ajuste se describe en el Capítulo 9
terminara si

Página 6
108 Fortran moderno explicado
Esto es útil, porque los códigos de error disponibles en la variable estadística dependen del procesador.
Cada objeto de asignación es asignable o un puntero. Se permite tener una longitud de caracteres cero.
Cada límite inferior y cada límite superior es una expresión entera escalar. El valor por defecto
para el límite inferior es 1. El número de límites de la matriz en una lista debe ser igual al rango de
asignar-objeto. Determinan los límites de la matriz, que no alteran si el valor de una variable
en una de las expresiones cambia posteriormente. Se puede asignar una matriz de tamaño cero.
Los límites de todos los arreglos que se asignan se consideran indefinidos durante la ejecución
de la instrucción de asignación, por lo que ninguna de las expresiones que especifican los límites puede depender
en cualquiera de los límites o en el valor de la variable stat =. Por ejemplo,
asignar (a (tamaño (b)), b (tamaño (a)))
! inválido
o incluso
asignar (a (n), b (tamaño (a)))
! inválido
no está permitido, pero
asignar (a (n))
asignar (b (tamaño (a)))
es válida. Esta restricción permite que el procesador realice las asignaciones en una sola asignación
declaración en cualquier orden.
A diferencia del caso con un objeto asignable, a un puntero se le puede asignar un nuevo objetivo
incluso si actualmente está asociado con un objetivo. En este caso, la asociación anterior está rota.
Si el objetivo anterior fue creado por asignación, se vuelve inaccesible a menos que otro puntero
está asociado con eso. Las listas vinculadas se crean normalmente utilizando un puntero único en un
Asignar sentencia para cada nodo de la lista. Hay un ejemplo en la Figura 4.9.
6.6 La declaración de desasignación
Cuando ya no se necesita un objeto asignable o un objetivo de puntero, se puede recuperar su almacenamiento
mediante el uso de la sentencia deallocate. Su forma general es
deallocate (allocate-object-list [, stat = stat] [, errmsg = erm])
donde cada objeto de asignación es un objeto asignable que se asigna o un puntero que es
asociado con el conjunto de un objetivo que se asignó a través de un puntero en una asignación
declaración. 1 Un puntero se desasocia (Sección 3.3) después de una ejecución exitosa
de la declaración. Aquí, stat es una variable entera escalar que no debe ser desasignada por
la declaración ni depende de un objeto que es desasignado por la declaración. Si stat = is
presente, stat recibe el valor cero después de una ejecución exitosa o un valor positivo
después de una ejecución fallida (por ejemplo, si un puntero está desasociado). Si hay un error durante
se produce la desasignación, se asigna un mensaje explicativo a la variable opcional errmsg =.
Después de una ejecución fallida, cada objeto que no fue desasignado correctamente conserva su
asignación previa o estado de asociación del puntero. Si stat = está ausente y la desasignación es
sin éxito, la ejecución se detiene.
Si hay más de un objeto en la lista, no debe haber dependencias entre ellos,
para permitir que el procesador desasigne los objetos uno por uno en cualquier orden. Un objeto no debe
1 Tenga en cuenta que esto excluye un puntero que está asociado con una matriz asignable.
Página 7
Asignación de datos 109
ser desasignado mientras él o un subobjeto está asociado con un argumento ficticio; esto puede
sucede, por ejemplo, si el objeto está en un módulo.
Un peligro al usar la declaración de desasignación es que un objeto puede desasignarse mientras
los punteros todavía están asociados con él. Tales punteros se dejan 'colgando' en un estado indefinido,
y no debe reutilizarse hasta que se vuelvan a asociar con un objetivo real.
Para evitar una acumulación de almacenamiento no utilizado e inutilizable, todos se asignan explícitamente
el almacenamiento se debe desasignar explícitamente cuando ya no sea necesario (esto es automático para
variables asignables locales no guardadas, consulte el final de la Sección 6.2). Esta gestión explícita es
requerido para evitar una sobrecarga potencialmente significativa por parte del procesador en
manejo de asignaciones arbitrariamente complejas y patrones de referencia.
Tenga en cuenta también que el estándar no especifica si el procesador recupera el almacenamiento
que tenía un objetivo asignado a través de un puntero pero que ya no es accesible a través de este o cualquier otro
otro puntero Esta falla para recuperar el almacenamiento se conoce como pérdida de memoria. Puede ser
importante donde, por ejemplo, se hace referencia a una función de puntero dentro de una expresión: la
el programador no puede confiar en el compilador para organizar la desasignación. Para asegurar que hay
sin pérdida de memoria, es necesario usar tales funciones solo en el lado derecho del puntero
asignaciones o como valores de componentes de puntero en constructores de estructura, y para desasignar el
puntero cuando ya no es necesario.
Los objetos asignables tienen la ventaja de que no pierden memoria, porque un
el objeto asignable no se puede asignar si ya está asignado, y se desasigna automáticamente
al regresar de un subprograma si es local al subprograma y no tiene el guardado
atributo.
6.7 Reasignación automática
La reasignación automática de matrices es posible y simplifica el uso de funciones de matriz que
devuelve un resultado de tamaño variable (como las funciones intrínsecas empacar y desempaquetar).
Por ejemplo, en
proceso de subrutina (x)
real (wp), intento (inout) :: x (:)
real (wp), asignable
:: valores no nulos (:)
valores_cero = paquete (x, x / = 0)
la matriz nonzero_values se asigna automáticamente para que tenga la longitud correcta para contener
los resultados del paquete de funciones intrínsecas, en lugar de que el usuario tenga que asignarlo manualmente
(lo que requeriría contar el número de nonzeros por separado). También permite un
extensión simple de una matriz asignable existente cuyos límites inferiores son todos 1. Para agregar algunos
valores adicionales para una matriz entera a de rango 1, es suficiente para escribir, por ejemplo,
a = [a, 5, 6]
Esta reasignación automática también ocurre si la variable asignable tiene un tipo diferido
parámetro que aún no tiene el mismo valor que el parámetro correspondiente de
la expresion. Esto se aplica tanto a escalares asignables como a matrices asignables, como en

Página 8
110 Fortran moderno explicado
carácter (:), asignable :: cita
...
quote = 'Ahora es el invierno de nuestro descontento'.
...
quote = "Este no es el verano del amor".
En cada una de las asignaciones a la cotización, se reasigna para que tenga la longitud correcta (a menos que
ya es de esa longitud) para mantener la cita deseada. Si en cambio el truncamiento normal o
se requiere relleno en una asignación a un carácter de longitud asignable, notación de subcadena
se puede usar para suprimir la reasignación automática. Por ejemplo,
cita (:) = ''
deja la cita en su longitud actual, configurando todo en blanco.
La reasignación automática solo ocurre para la asignación intrínseca normal, y no para la definida
asignación o para donde construye (Sección 7.6).
6.8 Transferencia de una asignación
La subrutina intrínseca move_alloc permite mover una asignación de un asignable
objetar a otro. Diferimos el caso de coarray a la Sección 17.6. Sin coarrays, la subrutina
es puro (Sección 7.8).
llame a move_alloc (from, to) donde:
from es asignable y de cualquier tipo. Tiene intención inout. No debe ser indexado
(Sección 17.4).
to es asignable y del mismo tipo y rango que from. Tiene intención. No debe
ser coindexado (Sección 17.4).
Después de la llamada, el estado de asignación de a es el de de antemano y de
desasignado Si to tiene el atributo target, cualquier puntero asociado con from
se asociará con a; de lo contrario, dicho puntero quedará indefinido.
Proporciona lo que es esencialmente el equivalente asignable de la asignación del puntero: asignación
transferir. Sin embargo, a diferencia de la asignación de puntero, esto mantiene la semántica asignable de
teniendo como máximo un objeto asignado para cada variable asignable. Por ejemplo,
real, asignable :: a1 (:), a2 (:)
asignar (a1 (0:10))
a1 (3) = 37
llame a move_alloc (de = a1, a = a2)
! a1 ahora no está asignado,
! a2 se asigna con límites (0:10) y a2 (3) == 37.
La subrutina move_alloc se puede usar para minimizar la cantidad de copia requerida cuando
uno desea expandir o contraer una matriz asignable; La secuencia canónica para esto es:

Página 9
Asignación de datos 111
real, asignable :: a (:, :), temp (:, :)
...
! Aumentar el tamaño de a a (n, m)
asignar (temp (n, m))
temp (1: tamaño (a, 1), 1: tamaño (a, 2)) = a
llame a move_alloc (temp, a)
! a ahora tiene forma (/ n, m /) y temp no está asignado
Esta secuencia solo requiere una operación de copia en lugar de las dos que hubieran sido
requerido sin move_alloc. Como el usuario controla la copia, los valores preexistentes
terminará donde el usuario los quiera (que podrían estar en los mismos subíndices, o todos en el
principio, o todo al final, etc.).
6.9 Argumentos ficticios asignables
Se permite que un argumento ficticio tenga el atributo asignable. En este caso, el
El argumento real correspondiente debe ser asignable y del mismo tipo, parámetros amables,
y rango; Además, la interfaz debe ser explícita. El argumento ficticio siempre recibe el
estado de asignación (descriptor) del argumento real en la entrada y el argumento real recibe
el del argumento ficticio al regreso. En ambos casos, esto puede estar sin asignar. Si se asigna,
los límites también se reciben (como para un puntero de matriz pero no una matriz de forma supuesta).
Nuestra expectativa es que algunos compiladores realizarán copias de entrada y salida del descriptor.
La regla i) de la sección 5.7.3 es aplicable y está diseñada para permitir que los compiladores hagan esto. En
en particular, esto significa que no hay referencia al argumento real (por ejemplo, si es
se permite una variable de módulo) desde el procedimiento invocado si se asigna la matriz ficticia
o desasignado allí.
Para el objeto en sí, la situación es como el caso cuando los argumentos reales y ficticios
son ambas matrices de forma explícita (ver Sección 5.7.4). Se permite la copia de copia a menos que ambas
Los objetos tienen el atributo de destino.
Se permite que un argumento ficticio asignable tenga intención y esto se aplica tanto a
estado de asignación (el descriptor) y al objeto mismo. Si la intención está dentro, el objeto no está
se permite asignar o desasignar y no se permite alterar el valor. Si el
la intención está fuera y el objeto se asigna en la entrada, se desasigna. Un ejemplo de la
Se muestra la aplicación de un argumento ficticio asignable para leer matrices de límites variables
en la figura 6.2.
6.10 Funciones asignables
Se permite que un resultado de función tenga el atributo asignable, que es muy útil cuando el
El tamaño del resultado depende de un cálculo en la función misma, como se ilustra en la Figura 6.3.
El estado de asignación en cada entrada a la función no está asignado. El resultado puede ser asignado
y desasignado cualquier número de veces durante la ejecución del procedimiento, pero debe ser
asignado y tener un valor definido en el retorno.

Página 10
112 Fortran moderno explicado
Figura 6.2 Lectura de matrices cuyo tamaño no se conoce de antemano.
carga de subrutina (matriz, unidad)
real, asignable, intento (fuera), dimensión (:,:, :) :: matriz
entero, intento (in)
:: unidad
entero
:: n1, n2, n3
leer *, n1, n2, n3
asignar (matriz (n1, n2, n3))
leer *, matriz
fin de la carga de subrutina
La interfaz debe ser explícita en cualquier unidad de alcance en la que se haga referencia a la función. los
el resultado se desasigna automáticamente después de la ejecución de la declaración en la que la referencia
se produce, incluso si tiene el atributo de destino.
Figura 6.3 Una función asignable para eliminar valores duplicados.
programa no_leak
real, dimensión (100) :: x, y
...
y (: tamaño (compacto (x))) = compacto (x) ** 2
...
contiene
¡Función compacta (x)! Para eliminar duplicados de la matriz x
dimensión real, asignable, (:) :: compacta
real, dimensión (:), intento (in) :: x
entero
:: n
...
! Encuentre el número de valores distintos, n
asignar (compacto (n))
...
! Copie los valores distintos en compacto
función final compacta
fin del programa no_leak
6.11 Componentes asignables
Los componentes de un tipo derivado pueden tener el atributo asignable. Por ejemplo,
se puede mantener una matriz triangular inferior usando una matriz asignable para cada fila. Considerar
el tipo
tipo de fila
real, dimensión (:), asignable :: r
fila de tipo final

Página 11
Asignación de datos 113
y las matrices
tipo (fila), dimensión (n) :: s, t
! n de tipo entero
El almacenamiento para las filas se puede asignar así
do i = 1, n
! i de tipo entero
asignar (t (i)% r (1: i))! Asignar fila i de longitud i
fin hacer
La asignación de matriz
s=t
entonces sería equivalente a las tareas
s (i)% r = t (i)% r
para todos los componentes
Para un objeto de un tipo derivado que tiene un componente de tipo derivado, necesitamos el concepto
de un componente asignable final, que es un componente final (Sección 2.13) que es
asignable Al igual que para un objeto asignable ordinario, el estado inicial de un último asignable
El componente no está asignado. Por lo tanto, no hay necesidad de inicialización predeterminada de asignables
componentes. De hecho, la inicialización en una definición de tipo derivado de un componente asignable es
no permitido, ver Sección 8.5.5.
En un constructor de estructura (Sección 3.9), una expresión correspondiente a un asignable
El componente debe ser un objeto o una referencia a la función intrínseca nula sin argumentos.
Si es un objeto asignable, el componente toma el mismo estado de asignación y, si está asignado,
los mismos límites y valor Si es un objeto, pero no asignable, el componente se asigna
con los mismos límites y se le asigna el mismo valor. Si es una referencia a lo intrínseco
función nula sin argumentos, el componente recibe el estado de asignación de no asignado.
Los componentes asignables se ilustran en la Figura 6.4, donde el código para manipular polinomi-
se muestra als con números variables de términos.
Un objeto de un tipo que tiene un componente asignable final puede tener
atributo de parámetro (ser una constante). En este caso, el componente siempre está sin asignar. Está
no se permite que aparezca en una declaración de asignación.
Cuando una variable de tipo derivado se desasigna, cualquier componente asignable final que
se asigna también se desasigna, como si fuera una declaración de desasignación. La variable puede ser
un puntero o asignable, y la regla se aplica de forma recursiva, de modo que todos los asignables asignables
los componentes en todos los niveles (aparte de los que se encuentran más allá de los componentes del puntero) se
desasignan.
Tales desasignaciones de componentes también ocurren cuando una variable está asociada con una intención de salida
argumento ficticio
Asignación intrínseca
variable = expr
para un tipo con un componente asignable final (como en r = p + q en la Figura 6.4) consiste
de los siguientes pasos para cada componente.
i) Si se asigna el componente de variable, se desasigna.
ii) Si se asigna el componente de expr, el componente de variable se asigna con el
mismos límites y el valor luego se transfiere mediante asignación intrínseca.

Pagina 12
114 Fortran moderno explicado
Figura 6.4 Uso de componentes asignables para agregar polinomios.
módulo real_polynomial_module
escriba real_polynomial
dimensión real, asignable, (:) :: coeff
tipo final polinomio real
operador de interfaz (+)
procedimiento de módulo rp_add_rp
operador de interfaz final (+)
contiene
función rp_add_rp (p1, p2)
tipo (polinomio real)
:: rp_add_rp
type (real_polynomial), intent (in) :: p1, p2
entero
:: m, m1, m2
m1 = ubound (p1% coeff, 1)
m2 = ubound (p2% coeff, 1)
asignar (rp_add_rp% coeff (max (m1, m2)))
m = min (m1, m2)
rp_add_rp% coeff (: m) = p1% coeff (: m) + p2% coeff (: m)
if (m1> m) rp_add_rp% coeff (m + 1 :) = p1% coeff (m + 1 :)
if (m2> m) rp_add_rp% coeff (m + 1 :) = p2% coeff (m + 1 :)
función final rp_add_rp
módulo final real_polynomial_module
ejemplo de programa
use real_polynomial_module
tipo (polinomio real) :: p, q, r
p = polinomio real ((/ 4.0, 2.0, 1.0 /))! Establezca p en 4 + 2x + x ** 2
q = polinomio real ((/ - 1.0, 1.0 /))
r=p+q
print *, 'Los coeficientes son:', r% coeff
ejemplo de programa final
Si el componente asignable de expr no está asignado, no sucede nada en el paso ii), por lo que
componente de variable se deja sin asignar. Tenga en cuenta que si el componente de la variable es
ya asignado con la misma forma, el compilador puede optar por evitar los gastos generales
de desasignación y reasignación. Tenga en cuenta también que si el compilador puede decir que habrá
sin referencia posterior a expr, porque es una referencia de función o una variable temporal
manteniendo el resultado de la evaluación de la expresión, no se necesita asignación o asignación, todo eso
tiene que suceder es la desasignación de los componentes asignables finales variables de variable
seguido de la copia del descriptor.
Si un componente es en sí mismo de un tipo derivado con un componente asignable, el intrínseco
la asignación en el paso ii) también involucrará estas reglas. De hecho, se aplican de forma recursiva en
todos los niveles, y la copia se produce en todos los casos. Esto se conoce como copia profunda, en oposición a

Página 13
Asignación de datos 115
copia superficial, que ocurre para los componentes del puntero, donde se copia el descriptor y
no se hace nada por los componentes de los componentes del puntero.
Si un argumento real y el argumento ficticio correspondiente tienen una asignación final
componente, la regla i) de la Sección 5.7.3 es aplicable y requiere todas las asignaciones y desasignaciones
del componente a realizar a través del argumento ficticio, en caso de que la copia de entrada sea
en efecto.
Si una declaración contiene una referencia a una función cuyo resultado es de un tipo con un último
componente asignable, cualquier componente asignable final asignado del resultado de la función
se desasignan después de la ejecución de la declaración. Esto es paralelo a la regla para la función asignable
resultados (Sección 6.10).
Figura 6.5 Ejemplo de lista asignable. La declaración leída aquí se explica en la Sección 10.7.
escriba my_real_list
valor real
tipo (my_real_list), asignable :: siguiente
tipo final
tipo (my_real_list), asignable, target :: list
type (my_real_list), puntero :: last
real :: x
...
last => null ()
hacer
leer (unidad, *, iostat = ios) x
si (ios / = 0) sale
if (.not.associated (last)) entonces
asignar (list, source = my_real_list (x))
last => list
más
asignar (último% siguiente, fuente = my_real_list (x))
last => last% next
terminara si
fin hacer
! La lista ahora contiene todos los valores de entrada, en orden de lectura.
...
¡desasignar (lista)! desasigna todos los elementos de la lista.
6.11.1 Componentes asignables de tipo recursivo
Se permite que un componente asignable sea de cualquier tipo derivado, incluido el tipo
definido o un tipo definido más adelante en la unidad de programa. Esto se puede usar para definir
estructuras dinámicas sin involucrar punteros, obteniendo así los beneficios habituales de asignables
variables: sin alias (excepto donde se utiliza el atributo de destino), contigüidad y automático
Página 14
116 Fortran moderno explicado
desasignación La desasignación automática significa que desasigna la variable principal (o devuelve
del procedimiento en el que se define) desasignará completamente toda la dinámica
estructura. La Figura 6.5 muestra cómo se puede usar esto para construir una lista (la cláusula source = causa
el tipo, los parámetros de tipo y los valores que se copiarán y se explica más adelante en la Sección 15.4). En
Al construir la lista en ese ejemplo, era conveniente usar un puntero al final de la lista.
Si, por otro lado, queremos insertar un nuevo valor en otro lugar (como al principio
de la lista), se recomienda el uso cuidadoso de move_alloc intrínseco (Sección 6.8) para evitar
haciendo copias temporales de toda la lista. Ilustramos esto con el impulso de subrutina para
Agregar un elemento a la parte superior de una pila en la Figura 6.6. Comentarios similares se aplican al elemento
eliminación, ilustrada por la subrutina pop en la Figura 6.6.
Figura 6.6 Procedimientos de pila asignables.
subrutina push (lista, nuevovalor)
type (my_real_list), allocatable :: list, temp
real, intención (en)
:: nuevo valor
llame a move_alloc (list, temp)
asignar (list, source = my_real_list (x))
llame a move_alloc (temp, list% next)
subrutina final
subrutina pop (lista)
type (my_real_list), allocatable :: list, temp
llame a move_alloc (list% next, temp)
llame a move_alloc (temp, list)
subrutina final
Uno podría imaginar que el compilador produciría un código similar (es decir, evitar el código
copias profundas) para las declaraciones mucho más simples
list = my_real_list (nuevovalor, lista)
y
lista = lista% siguiente
como las partes ejecutables de push y pop, respectivamente, pero de hecho el modelo para asignable
la asignación en el estándar especifica la desasignación automática solo cuando una forma de matriz, longitud
parámetro de tipo o tipo dinámico difiere; ese no es el caso en estos ejemplos, entonces el compilador
Se espera que realice una copia profunda. (Un programa conforme a la norma solo puede decirle al
diferencia cuando el tipo tiene subrutinas finales o la lista tiene el atributo de destino; Así que si
las variables involucradas no son polimórficas ni objetivos, un compilador podría producir más
código óptimo.)
6.12 Matrices asignables frente a punteros
¿Por qué se necesitan matrices asignables? ¿Toda su funcionalidad no está disponible (y más) con
punteros? La razón es que hay ventajas significativas para la administración de memoria y

Página 15
Asignación de datos 117
velocidad de ejecución en el uso de matrices asignables cuando la funcionalidad agregada de punteros no es
necesario.
• Es probable que el código para un puntero de matriz sea menos eficiente porque la asignación tiene que
hacerse para otros pasos que no sean la unidad. Por ejemplo, su objetivo podría ser la sección
vector (1: n: 2) o la matriz de sección (i, 1: n) con zancadas sin unidad, mientras que la mayoría
Las computadoras tienen matrices asignables en la memoria contigua.
• Si una operación definida involucra una variable temporal de un tipo derivado con un puntero
componente, el compilador probablemente no podrá desasignar su destino cuando el almacenamiento
para la variable se libera. Considere, por ejemplo, la declaración
a=b+c*d
! a, b, cyd son del mismo tipo derivado
Esto creará un temporal para c * d, que no es necesario una vez que b + c * d ha sido
calculado. Es poco probable que el compilador se asegure de que ningún otro puntero tenga el componente
o parte de él como un objetivo, por lo que es poco probable que lo desasigne.
• La asignación intrínseca a menudo no es adecuada para un tipo derivado con un componente puntero
porque la tarea
a=b
dejará a y b compartiendo el mismo objetivo para su componente puntero. Por lo tanto, un
En su lugar, se utilizará una asignación definida que asigna un nuevo objetivo y copia los datos.
Sin embargo, esto es muy derrochador si el lado derecho es temporal como el del
asignación del párrafo anterior.
• Se aplican consideraciones similares a una invocación de función dentro de una expresión. los
es poco probable que el compilador pueda desasignar el puntero después de que la expresión tenga
ha sido calculado
• Cuando una variable de tipo derivado se desasigna, cualquier componente asignable final que
se asigna también se desasigna. Para evitar pérdidas de memoria con componentes del puntero, el
el programador necesitaría desasignar cada uno explícitamente y tener cuidado de ordenar el
desasignaciones correctamente.
Aunque el estándar Fortran no menciona descriptores, es muy útil pensar en
una matriz asignable como un descriptor que registra si está asignada y, si
entonces, su dirección y sus límites en cada dimensión. Esto es como un descriptor para un puntero, pero no
se necesitan avances ya que estos son siempre la unidad. En cuanto a los punteros, la expectativa es que el
matriz en sí se lleva a cabo por separado.
6.13 Resumen
Hemos descrito cómo la asignación de almacenamiento para un objeto puede ser controlada en detalle por un
programa.

Página 16
118 Fortran moderno explicado
Ejercicios
1. Usando el tipo real_polynomial de la Figura 6.4 en la Sección 6.11, escriba el código para definir una variable de
ese tipo con una longitud de componente asignable de cuatro y luego extender esa matriz asignable con
Dos valores adicionales.
2. Dado el tipo
escriba emfield
real, asignable :: fuerza (:, :)
tipo final
inicialice una variable de tipo emfield para que su componente tenga límites (1: 4,1: 6) y valor 1
en todos lados. Extienda esta variable para que el componente tenga límites (0: 5,0: 8), manteniendo los valores de
los elementos antiguos y establecer los valores de los nuevos elementos a cero.
3. Como el ejercicio 2, pero con nuevos límites (1: 6,1: 9) y utilizando la función intrínseca de remodelación.
4. Escriba una declaración que haga una matriz entera de rango 2 existente b, que tenga límites inferiores de 1, dos
filas y dos columnas más grandes, con los valores de los elementos antiguos retenidos en el medio de la matriz.
(Sugerencia: utilice la función intrínseca de remodelación).

Página 17

7. Características de la matriz
7.1 Introducción
En una era en que muchas computadoras tienen la capacidad de hardware para el procesamiento eficiente de la matriz
operandos, es evidente que un lenguaje de base numérica como Fortran debería tener
emparejar instalaciones de notación. Dichas instalaciones proporcionan no solo conveniencia de notación para
programador, pero también brinda una oportunidad para mejorar la optimización.
Las matrices se introdujeron en las Secciones 2.10 a 2.12, su uso en expresiones simples y en
las tareas se explicaron en las Secciones 3.11 y 3.12, y se usaron como procedimiento
argumentos en el Capítulo 5. Estas descripciones fueron restringidas deliberadamente porque Fortran
contiene un conjunto muy completo de funciones de matriz cuya descripción completa habría desequilibrado
esos capítulos El propósito de este capítulo es describir las características de la matriz en detalle, pero
sin anticipar las descripciones de los procedimientos intrínsecos de la matriz del Capítulo 9; los ricos
El conjunto de procedimientos intrínsecos debe considerarse una parte integral de las características de la matriz.
7.2 matrices de tamaño cero
Se podría pensar que una matriz siempre tendría al menos un elemento. Sin embargo, tal
un requisito obligaría a los programas a contener código adicional para lidiar con ciertas
situaciones Por ejemplo, el código en la Figura 7.1 resuelve un conjunto triangular inferior de lineal
ecuaciones Cuando tengo el valor n, las secciones tienen un tamaño cero, que es justo lo que se requiere.
Figura 7.1 Un ciclo do cuya iteración final tiene una matriz de tamaño cero.
do i = 1, n
x (i) = b (i) / a (i, i)
b (i + 1: n) = b (i + 1: n) - a (i + 1: n, i) * x (i)
fin hacer
Fortran permite que las matrices tengan un tamaño cero en todos los contextos. Cada vez que un límite inferior excede
el límite superior correspondiente, la matriz tiene tamaño cero.
Sin embargo, existen pocas reglas especiales para las matrices de tamaño cero porque siguen las reglas habituales.
Puede ser necesario un poco de cuidado en su interpretación. Por ejemplo, dos matrices de tamaño cero de la
El mismo rango puede tener diferentes formas. Uno podría tener forma (0,2) y el otro (0,3) o (2,0).
Fortran moderno explicado, 2da edición. Michael Metcalf, John Reid y Malcolm Cohen. prensa de la Universidad de Oxford
(2018) cG Michael Metcalf, John Reid y Malcolm Cohen 2018. DOI 10.1093 / oso / 9780198811893.001.0001

Página 18
120 Fortran moderno explicado
Tales conjuntos de formas diferentes no son conformes y, por lo tanto, no se pueden usar juntos como
Los operandos de una operación binaria. Sin embargo, una matriz siempre es compatible con un escalar
la declaración
matriz de tamaño cero = escalar
es válido y el escalar se 'transmite a todos los elementos de la matriz', lo que hace que sea un 'no hacer nada'
declaración.
Una matriz de tamaño cero se considera definida siempre, porque no tiene valores que puedan
ser indefinido
7.3 objetos automáticos
Un procedimiento con argumentos ficticios que son matrices cuyo tamaño varía de una llamada a otra puede
También se necesitan matrices locales cuyo tamaño varía. Un ejemplo simple es el trabajo de matriz en la subrutina
para intercambiar dos matrices que se muestran en la Figura 7.2.
Figura 7.2 Un procedimiento con una matriz automática; el tamaño se describe en la Sección 9.14.2.
cambio de subrutina (a, b)
real, dimension (:), intent (inout) :: a, b
real, dimensión (tamaño (a))
:: trabajo ! matriz automática
! tamaño proporciona el tamaño de una matriz
trabajo = a
a=b
b = trabajo
fin del intercambio de subrutinas
Una matriz cuyas extensiones varían de esta manera se llama una matriz automática, y es un ejemplo
de un objeto de datos automático. Tal objeto no es un argumento ficticio y su declaración
contiene uno o más valores que no se conocen en tiempo de compilación; es decir, no es una constante
expresión (Sección 8.4). Es probable que una implementación los haga realidad cuando
Se llama al procedimiento y destrúyalos al regresar, manteniéndolos en una pila. 1 Los valores
debe definirse mediante expresiones de especificación (Sección 8.18).
Otra forma en que surgen los objetos automáticos es variando la longitud de los caracteres. La variable
palabra2 en
ejemplo de subrutina (palabra1)
carácter (len = *), intento (entrada) :: palabra1
carácter (len = len (palabra1))
:: word2
Es un ejemplo. Si el resultado de una función tiene una longitud de caracteres variable, la interfaz debe ser explícita
en el punto de la llamada porque el compilador necesita saber esto, como se muestra en la Figura 7.3.
Un tipo derivado parametrizado (Sección 13.2) puede tener un parámetro de tipo de longitud que se comporte
muy similar a la longitud de los caracteres, y un argumento ficticio de ese tipo puede ser un objeto automático.
Aplazamos la discusión de esto a la Sección 13.2.2.
1 Una pila es un mecanismo de administración de memoria mediante el cual se establece un almacenamiento nuevo y se descarta el almacenamiento antiguo
sobre una base de "último en entrar, primero en salir", a menudo dentro de la memoria contigua.

Página 19
Funciones de matriz 121
Figura 7.3 Un módulo que contiene un procedimiento con un escalar automático.
programa loren
carácter (len = *), parámetro :: a = 'solo una prueba simple'
print *, doble (a)
contiene
función doble (a)
carácter (len = *), intento (in) :: a
carácter (len = 2 * len (a))
:: doble
doble = a // a
función final doble
programa final loren
Una matriz vinculada o la longitud de caracteres de un objeto automático se fija durante la duración de
cada ejecución del procedimiento y no varía si el valor de la expresión de especificación
varía o se vuelve indefinido.
A un objeto automático no se le debe dar el atributo guardar, vea la Sección 8.10, porque esto
es obviamente contrario a ser automático; y no se le debe dar un valor inicial, ver
Secciones 8.5.1 y 8.5.2, porque esto le da el atributo guardar.
7.4 Operaciones elementales y tareas
Vimos en la Sección 3.11 que un operador intrínseco puede aplicarse a operandos conformes, para
producir un resultado de matriz cuyos valores de elementos son los valores de la operación aplicada a
elementos correspondientes de los operandos. Tal operación se llama elemental.
No es esencial utilizar la notación de operador para obtener este efecto. Muchos de los intrínsecos
los procedimientos (Capítulo 9) son elementales y tienen argumentos ficticios escalares que pueden llamarse
con argumentos reales de matriz siempre que todos los argumentos de matriz tengan la misma forma. Tal
referencia se llama referencia elemental. Para una función, la forma del resultado es la forma
de los argumentos de la matriz. Por ejemplo, podemos encontrar las raíces cuadradas de todos los elementos de un
matriz real a por lo tanto:
a = sqrt (a)
Si cualquier argumento real en una invocación de subrutina tiene valor de matriz, todos los argumentos reales
correspondientes a argumentos ficticios con intento de salida o entrada deben ser matrices. Si un procedimiento
que invoca un procedimiento elemental tiene un argumento ficticio opcional con valores de matriz que es
ausente, ese argumento ficticio no debe usarse como argumento real en el elemento
invocación a menos que otra matriz del mismo rango esté asociada con un argumento no opcional
del procedimiento elemental (para garantizar que el rango no varíe de una llamada a otra).
Del mismo modo, una asignación intrínseca puede usarse para asignar un escalar a todos los elementos de un
matriz, o para asignar cada elemento de una matriz al elemento correspondiente de una matriz de la
misma forma (Sección 3.12). Tal asignación también se llama elemental.
Para un operador definido, se puede obtener un efecto similar con una interfaz genérica para funciones
para cada rango o par de rangos deseado. Por ejemplo, el módulo de la Figura 7.4 proporciona

Página 20
122 Fortran moderno explicado
Figura 7.4 Adición de intervalo para escalares y matrices de rango uno.
módulo intervalo_adición
intervalo de tipo
real :: inferior, superior
intervalo de tipo final
operador de interfaz (+)
procedimiento de módulo add00, add11
interfaz final
contiene
función add00 (a, b)
tipo (intervalo)
:: add00
tipo (intervalo), intento (in) :: a, b
¡add00% más bajo = a% más bajo + b% más bajo! Código de producción
add00% upper = a% upper + b% upper! permitir el redondeo.
función final add00
función add11 (a, b)
tipo (intervalo), dimensión (:), intento (in)
:: una
tipo (intervalo), dimensión (tamaño (a))
:: add11
tipo (intervalo), dimensión (tamaño (a)), intención (in) :: b
¡add11% más bajo = a% más bajo + b% más bajo! Código de producción
add11% upper = a% upper + b% upper! permitir el redondeo.
función final add11
módulo final intervalo_adición
suma para escalares y matrices de intervalos de rango uno (Sección 3.9). Alternativamente, un
El procedimiento elemental se puede definir para este propósito (Sección 7.9).
Del mismo modo, las versiones elementales de las tareas definidas se pueden proporcionar explícitamente o un
El procedimiento elemental se puede definir para este propósito (Sección 7.9).
7.5 Funciones con valores de matriz
Mencionamos en la Sección 5.10 que una función puede tener un resultado de valor de matriz, y ha utilizado
Esta característica del lenguaje en la Figura 7.4 donde la interpretación es obvia.
Para que el compilador conozca la forma del resultado, la interfaz debe ser explícita
(Sección 5.11) siempre que se haga referencia a dicha función. La forma se especifica dentro de
definición de función por el atributo de dimensión para el nombre de la función. A menos que la función
el resultado es asignable o un puntero, los límites deben ser expresiones explícitas y son
evaluado al ingresar a la función. Para otro ejemplo, vea la declaración de la función
resultado en la Figura 7.5.
Una función con valor de matriz no es necesariamente elemental. Por ejemplo, al final de
Sección 3.11 consideramos el tipo

Página 21
Funciones de matriz 123
Figura 7.5 Una función para matriz por multiplicación vectorial; el tamaño se define en la Sección 9.14.
función mult (a, b)
tipo (matriz), dimensión (:, :)
:: una
tipo (matriz), dimensión (tamaño (a, 2)) :: b
tipo (matriz), dimensión (tamaño (a, 1)) :: mult
entero
:: j, n
mult = 0.0
! Una asignación definida de un real
! escalar a una matriz de rango uno.
n = tamaño (a, 1)
do j = 1, tamaño (a, 2)
mult = mult + a (1: n, j) * b (j)
! Utiliza operaciones definidas para la adición de
! dos matrices de rango uno y multiplicación
! de una matriz de rango uno por una matriz escalar.
fin hacer
función final mult
tipo de matriz
real :: elemento
matriz de tipo final
Sus operaciones escalares y de rango uno pueden ser como las reales, pero para multiplicar una matriz de rango dos
mediante una matriz de rango uno, podríamos usar la función del módulo que se muestra en la Figura 7.5 para
proporcionar una matriz
por multiplicación vectorial.
7.6 La declaración y la construcción where
A menudo se desea realizar una operación de matriz solo para ciertos elementos, digamos aquellos cuya
Los valores son positivos. La declaración where proporciona esta facilidad. Un ejemplo simple es
donde (a> 1.0) a = 1.0 / a
! a es una matriz real
que corresponde a los elementos de a que son mayores que 1.0 y deja el resto sin alterar.
La forma general es
donde (logical-array-expr) array-variable = expr
La expresión de matriz lógica logical-array-expr se conoce como máscara y debe tener
misma forma que la variable de matriz. Primero se evalúa y luego solo los elementos de expr
que corresponden a elementos de logical-array-expr que tienen el valor verdadero se evalúan y
se asignan a los elementos correspondientes de la variable de matriz. Todos los demás elementos de la matriz
Las variables no se modifican. La asignación puede ser una asignación definida, siempre que sea
elemental (Sección 7.9).
Se puede usar una sola expresión de enmascaramiento para una secuencia de asignaciones de matriz todas las
Misma forma. La forma más simple de esta construcción es

Página 22
124 Fortran moderno explicado
donde (logical-array-expr)
asignaciones de matrices
termina donde
La expresión de enmascaramiento logical-array-expr se evalúa primero y luego cada asignación de matriz
se realiza a su vez, bajo el control de esta máscara. Si alguna de estas asignaciones afecta a entidades
en logical-array-expr, siempre es el valor obtenido cuando se ejecuta la instrucción where
eso se usa como la máscara.
La construcción where puede tomar la forma
donde (logical-array-expr)
asignaciones de matrices
en otra parte
asignaciones de matrices
termina donde
Aquí, las asignaciones en el primer bloque de asignaciones se realizan a su vez bajo el control
de logical-array-expr y luego las asignaciones en el segundo bloque se realizan a su vez
bajo el control de .not.logical-array-expr. Nuevamente, si alguna de estas asignaciones afecta
entidades en logical-array-expr, siempre es el valor obtenido cuando la instrucción where es
ejecutado que se utiliza como la máscara.
Un ejemplo simple de una construcción donde es
donde (presión <= 1.0)
presión = presión + presión inc
temp = temp + 5.0
en otra parte
lloviendo = .verdadero.
termina donde
donde presión, presión adicional, temperatura y lluvia son conjuntos de la misma forma.
Si una instrucción o construcción where enmascara una referencia de función elemental, la función es
llamado solo para los elementos deseados. Por ejemplo,
donde (a> 0) a = log (a)
(el registro se define en la Sección 9.4) no daría lugar a llamadas erróneas de registro para negativo
argumentos
Esta máscara se aplica a todas las referencias de funciones elementales, excepto las que se encuentran dentro de un
argumento de una referencia de función no elemental. El enmascaramiento no se extiende a la matriz
argumentos de tal función. En general, tales argumentos tienen una forma diferente para que
el enmascaramiento no sería posible. Por ejemplo, en el caso
donde (a> 0) a = a / sum (log (a))
(la suma se define en la Sección 9.13) se suman los logaritmos de cada uno de los elementos de a y
la declaración fallará si no todos son positivos.
Si se enmascara una referencia de función no elemental o un constructor de matriz, se evalúa completamente
antes de aplicar el enmascaramiento.
Está permitido enmascarar no solo la instrucción where de la construcción where, sino también cualquier
declaración en otro lugar que contiene. Todas las expresiones de enmascaramiento deben ser iguales

Página 23
Características de matriz 125
forma. Una construcción where puede contener cualquier número de declaraciones enmascaradas en otro lugar, pero en
la mayoría de una declaración en otro lugar sin máscara, y si está presente, esta debe ser la última. En
Además, donde las construcciones pueden estar anidadas entre sí; todas las expresiones de enmascaramiento de
la construcción anidada debe tener la misma forma, y esta debe ser la forma de toda la matriz
variables en el lado izquierdo de las asignaciones dentro de la construcción.
Una declaración simple donde, como la que se encuentra al comienzo de esta sección, está permitida dentro de un
donde construye y se interpreta como si fuera la construcción correspondiente que contiene
Una asignación de matriz.
Finalmente, una construcción where se puede nombrar de la misma manera que otras construcciones.
Un ejemplo que ilustra más complicado donde las construcciones que se nombran se muestra en
Figura 7.6.
Figura 7.6 Anidado donde construye, mostrando el enmascaramiento.
asignar_1: donde (cond_1)
...
! enmascarado por cond_1
en otro lugar (cond_2)
...
! enmascarado por
...
! cond_2.and..not.cond_1
asignar_2:
donde (cond_4)
...
! enmascarado por
...
! cond_2.and..not.cond_1.and.cond_4
en otra parte
...
! enmascarado por
...
! cond_2.and..not.cond_1.and..not.cond_4
terminar donde asignar_2
...
en otro lugar (cond_3) asignar_1
...
! enmascarado por
...
! cond_3.and..not.cond_1.and..not.cond_2
en otro lugar asignar_1
...
! enmascarado por
...
! not.cond_1.and..not.cond_2.and..not.cond_3
terminar donde asignar_1
Todas las declaraciones de una construcción where se ejecutan una por una en secuencia, incluida la
donde y en otros lugares declaraciones. Las expresiones de enmascaramiento en dónde y en otros lugares
las declaraciones se evalúan una vez y el control de las asignaciones posteriores no se ve afectado por
cambios en los valores de estas expresiones. A lo largo de una construcción donde hay un control

Página 24
126 Fortran moderno explicado
máscara y una máscara pendiente que cambian después de la evaluación de cada lugar, en otro lugar, y
terminar donde la declaración, como se ilustra en la Figura 7.6.
7.7 Conjuntos de máscaras
Se necesitan matrices lógicas para enmascarar en donde las declaraciones y construcciones (Sección 7.6),
y juegan un papel similar en muchas de las funciones intrínsecas de la matriz (Capítulo 9). Tal
las matrices a menudo son grandes, y puede haber una ganancia de almacenamiento que valga la pena al usar
tipos lógicos, si están disponibles. Por ejemplo, algunos procesadores pueden usar bytes para almacenar elementos
de matrices lógicas (kind = 1) y bits para almacenar elementos de matrices lógicas (kind = 0).
Desafortunadamente, no hay una instalación portátil para especificar tales matrices, ya que no hay intrínseca
función comparable a selected_int_kind y selected_real_kind.
Las matrices lógicas se forman implícitamente en ciertas expresiones, generalmente como compiladas
variables temporales En
donde (a> 0.0) a = 2.0 * a
o
si (cualquiera (a> 0.0)) entonces
(cualquiera se describe en la Sección 9.13.1) la expresión a> 0.0 es una matriz lógica. En semejante
En este caso, se puede esperar que un compilador optimizador elija un parámetro de tipo de tipo adecuado para
matriz temporal
7.8 Procedimientos puros
En la descripción de funciones en la Sección 5.10 notamos que, aunque está permitido escribir
funciona con efectos secundarios, esto se considera indeseable. Es posible para el programador
para afirmar que un procedimiento no tiene efectos secundarios al agregar la palabra clave pura a la subrutina
o declaración de función. Declarar que un procedimiento es puro es una afirmación de que el procedimiento
i) si es una función, no altera ningún argumento ficticio;
ii) no altera ninguna parte de una variable a la que accede el host o la asociación de uso;
iii) no contiene ninguna variable local con el atributo save (Sección 8.10);
iv) no realiza ninguna operación en un archivo externo (capítulos 10 y 12);
v) no contiene ninguna declaración de detención o detención de error (Sección 17.14); y
vi) no contiene ninguna declaración de control de imagen (Sección 17.13).
Para garantizar que se cumplan estos requisitos y que un compilador pueda verificar fácilmente que esto es
entonces, existen las siguientes reglas adicionales:
i) Cualquier argumento ficticio que sea un procedimiento, y cualquier procedimiento al que se haga referencia, debe ser
puro
y tener una interfaz explícita.
ii) La intención de un argumento ficticio debe declararse a menos que sea un procedimiento o un puntero
o tiene el atributo de valor, y esta intención debe estar en el caso de una función.
iii) Cualquier procedimiento interno a un procedimiento puro debe ser puro.

Página 25
Funciones de matriz 127
iv) Una variable a la que accede el host o la asociación de uso, es una intención en un argumento ficticio,
es un objeto coindexado (Sección 17.4), o cualquier parte de dicha variable no debe usarse
de cualquier manera que pueda alterar su valor o estado de asociación de puntero, o hacer que sea el
objetivo de un puntero.
Esta última regla asegura que un puntero local no pueda causar un efecto secundario.
La función en la Figura 5.6 (Sección 5.10) es pura, y esto podría especificarse explícitamente:
distancia de función pura (p, q)
Un procedimiento externo o ficticio que se utiliza como procedimiento puro debe tener una interfaz
bloque que lo especifica como puro. Sin embargo, el procedimiento puede usarse en otros contextos sin
el uso de un bloque de interfaz o con un bloque de interfaz que no lo especifica como puro. Esta
permite que los procedimientos de la biblioteca se especifiquen como puros sin limitarlos a ser utilizados como tales.
A diferencia de las funciones puras, las subrutinas puras pueden tener argumentos ficticios que tienen intenciones
o inout o el atributo puntero. La razón principal ahora para permitir subrutinas puras es
ser capaz de usar una asignación definida en una declaración de hacer concurrente (Sección 7.17). 2 Su
la existencia también brinda la posibilidad de realizar llamadas de subrutina desde funciones puras.
Todas las funciones intrínsecas (Capítulo 9) son puras y, por lo tanto, pueden ser referenciadas libremente dentro de
procedimientos puros Además, la subrutina intrínseca elemental mvbits (Sección 9.10.5) es pura.
El atributo puro se otorga automáticamente a cualquier procedimiento que tenga el atributo elemental
(Siguiente sección).
7.9 Procedimientos elementales
Ya hemos conocido la noción de procedimientos intrínsecos elementales (Sección 7.4) - aquellos con
argumentos ficticios escalares que se pueden invocar con argumentos reales de matriz siempre que
Los argumentos de matriz tienen la misma forma (es decir, siempre que todos los argumentos sean conformes).
Para una función, la forma del resultado es la forma de los argumentos de la matriz. Esta característica también
existe para procedimientos no intrínsecos. Esto requiere el prefijo elemental en la función o
declaración de subrutina. Por ejemplo, podríamos hacer que la función add_intervals de Section
3.9 elemental, como se muestra en la Figura 7.7. Esto es una ayuda para la optimización en procesadores paralelos.
Figura 7.7 Una función elemental.
función elemental add_intervals (a, b)
tipo (intervalo)
:: add_intervals
tipo (intervalo), intento (in) :: a, b
add_intervals% lower = a% lower + b% lower! Codigo de producción
add_intervals% upper = a% upper + b% upper! permitiría
función final add_intervals
! redondear.
A menos que se use el prefijo impuro, consulte la Sección 7.10, un procedimiento elemental automáticamente
tiene el atributo puro Además, cualquier argumento ficticio debe ser una variable escalar que no sea
una matriz (Capítulo 17), no es asignable y no es un puntero; y el resultado de una función debe ser
2 Losprocedimientos puros se introdujeron originalmente para admitir la característica general (Sección B.3.1), ahora reemplazada por
hacer concurrente

Página 1
128 Fortran moderno explicado
una variable escalar que no es asignable, no es un puntero y no tiene un parámetro de tipo
definido por una expresión que no sea una expresión constante.
Se requiere un bloque de interfaz para un procedimiento externo si el procedimiento en sí no es
intrínseco y elemental. La interfaz debe especificarlo como elemental. Esto es porque el
el compilador puede usar un mecanismo de llamada diferente para acomodar el caso de la matriz
eficientemente. Contrasta con el caso de los procedimientos puros, donde se permite más libertad
(ver sección anterior).
Para una subrutina elemental, si cualquier argumento real tiene un valor de matriz, todos los argumentos reales
correspondientes a argumentos ficticios con intención de entrada o salida deben ser matrices. Por ejemplo,
podemos hacer que el cambio de subrutina de la Figura 7.2 (Sección 7.3) realice su tarea en matrices de
cualquier forma o tamaño, como se muestra en la Figura 7.8. Llamar a swap con una matriz y un argumento escalar
obviamente es erróneo y no está permitido.
Figura 7.8 Versión elemental de la subrutina de la Figura 7.2.
intercambio de subrutina elemental (a, b)
real, intento (inout) :: a, b
real
:: trabajo
trabajo = a
a=b
b = trabajo
fin del intercambio de subrutinas
Si una referencia de procedimiento genérico (Sección 5.18) es consistente con un elemento elemental y
un procedimiento no elemental, se invoca el procedimiento no elemental. Por ejemplo, podríamos
escriba versiones de add_intervals (Figura 7.7) para matrices de rango uno y confíe en el elemento
función para otros rangos. En general, uno debe esperar que la versión elemental ejecute más
lentamente para un rango específico que la versión no elemental correspondiente.
Notamos que un procedimiento elemental no intrínseco no puede usarse como argumento real.
No se permite que un procedimiento sea tanto elemental como recursivo. 3
7.10 Procedimientos elementales impuros
Los procedimientos elementales que son puros son una ayuda para la evaluación paralela. También permiten un
función única para reemplazar funciones separadas para cada permutación de rangos conformes; para
procedimiento con dos argumentos, es decir 46 procedimientos separados (16 casos donde ambos argumentos
tienen el mismo rango, 15 donde el primero era escalar y el segundo es una matriz, y 15 donde el
primero es una matriz y el segundo era escalar).
El prefijo impuro en el encabezado del procedimiento permite obtener este efecto cuando la función
No es puro. Procesa elementos de argumento de matriz uno por uno en orden de elemento de matriz. Un
El ejemplo se muestra en la Figura 7.9. Este ejemplo es impuro de tres maneras: cuenta el número
de desbordamientos en la variable global overflow_count, registra cada desbordamiento en el externo
unit error_unit, y finaliza la ejecución con stop cuando se han producido demasiados errores
encontrado
3 Esta restricción se elimina en Fortran 2018, consulte la Sección 23.14.

Página 2
Funciones de matriz 129
Figura 7.9 Una función elemental impura. La declaración de escritura se describe en el Capítulo 11.
módulo safe_arithmetic
entero :: max_overflows = 1000
entero :: overflow_count = 0
contiene
función entera elemental impura cuadrado (n)
use iso_fortran_env, solo: error_unit
entero, intento (in) :: n
doble precisión, parámetro :: sqrt_huge = &
sqrt (real (enorme (n), tipo (0d0)))
if (abs (n)> sqrt_huge) entonces
write (error_unit, *) 'Desbordamiento en cuadrado (', n, ')'
overflow_count = overflow_count + 1
if (overflow_count> max_overflows) detiene '? Demasiados desbordamientos'
cuadrado = enorme (n)
más
cuadrado = n ** 2
terminara si
función final
módulo final
Solo se eliminan los requisitos relacionados con la 'pureza' (falta de efectos secundarios): el elemento
los requisitos permanecen, es decir:
• cada argumento ficticio debe ser un objeto de datos ficticios escalar sin matriz, no debe
tener el puntero o el atributo asignable y debe tener una intención específica o
el atributo de valor;
• si el procedimiento es una función, su resultado debe ser escalar, no debe tener el puntero o
atributo asignable, y no debe tener una expresión de parámetro de tipo que dependa de
el valor de un argumento ficticio, sobre el valor de un parámetro de tipo diferido de un ficticio
argumento, o en los límites de un puntero o matriz ficticia asignable;
• en referencia al procedimiento, todos los argumentos reales deben ser conformes; y
• en una referencia al procedimiento, argumentos reales correspondientes a la intención y
Todos los argumentos ficticios deben ser matrices o todos deben ser escalares.
7.11 Elementos de matriz
En la Sección 2.10 restringimos la descripción de los elementos de la matriz a casos simples. En general, un
elemento de matriz es un escalar de la forma
ref-parte [% ref-parte]. . .
donde parte-ref es
nombre-parte [(lista de subíndices)]

Página 3
130 Fortran moderno explicado
y la última referencia parcial tiene una lista de subíndices. El número de subíndices en cada lista debe ser
igual al rango de la matriz o componente de la matriz, y cada subíndice debe ser un escalar
expresión entera cuyo valor está dentro de los límites de la dimensión de la matriz o matriz
componente. Para ilustrar esto, tome el tipo
tipo triplete
real
:: u
real, dimensión (3)
:: du
real, dimensión (3,3) :: d2u
triplete de tipo final
que se consideró en la Sección 2.10. Se puede declarar una matriz de este tipo:
tipo (triplete), dimensión (10,20,30) :: alquitrán
y
alquitrán (n, 2, n * n)
! n de tipo entero
Es un elemento de matriz. Es un escalar de tipo triplete y
alquitrán (n, 2, n * n)% du
es una matriz real con
alquitrán (n, 2, n * n)% du (2)
como uno de sus elementos
Si un elemento de matriz es de tipo carácter, puede ser seguido por una referencia de subcadena:
(rango de subcadena)
por ejemplo,
página (k * k) (i + 1: j-5)! i, j, k de tipo entero
Por convención, dicho objeto se llama una subcadena en lugar de un elemento de matriz.
Observe que es el nombre de la parte de la matriz que califica la lista de subíndices. No esta permitido
para aplicar dicha lista de subíndices a un designador de matriz a menos que el designador termine con un
nombre de parte de la matriz. Una sección de matriz, una referencia de función o una expresión de matriz entre paréntesis
no debe estar calificado por una lista de subíndices.
7.12 Subobjetos de matriz
Las secciones de matriz se introdujeron en la Sección 2.10 y proporcionan una forma conveniente de acceder a un
subarreglos regulares como una fila o una columna de una matriz de rango dos:
a (i, 1: n)
! Elementos 1 a n de la fila i
a (1: m, j)
! Elementos 1 am de la columna j
Para simplificar la descripción, no explicamos que uno o ambos límites pueden omitirse cuando
se desea el límite correspondiente de la matriz en sí, y que un paso distinto de uno puede ser
especificado:
a (i, :)
! Toda la fila i
a (i, 1: n: 3)
! Elementos 1, 4, ... de la fila i

Página 4
Funciones de matriz 131
Otra forma de subíndice de sección es una expresión entera de rango uno. Todos los elementos de
la expresión debe definirse con valores que se encuentren dentro de los límites de la matriz principal
subíndice. Por ejemplo, dada una matriz v de extensión 8,
v ([1, 7, 3, 2])
es una sección con los elementos v (1), v (7), v (3) y v (2), en este orden. Tal subíndice es
llamado subíndice vectorial. Si hay repeticiones en los valores de los elementos de un vector
subíndice, la sección se llama una sección de muchos porque uno de los elementos de
La sección se asigna a un único elemento de matriz. Por ejemplo,
v ([1, 7, 3, 7])
tiene elementos 2 y 4 mapeados en v (7). Una sección de muchos no debe aparecer a la izquierda de
una declaración de asignación porque habría varios valores posibles para un solo elemento.
Por ejemplo, la declaración
v ([1, 7, 3, 7]) = [1, 2, 3, 4]
! Inválido
no está permitido porque los valores 2 y 4 no pueden almacenarse en v (7). La extensión es cero si
el subíndice del vector tiene tamaño cero. Tenga en cuenta que, con una repetición suficiente de valores de subíndice,
la sección en realidad puede ser más larga que la matriz principal.
Cuando una sección de matriz con un subíndice vectorial es un argumento real en una llamada de un
procedimiento elemental, se considera como una expresión y el argumento ficticio correspondiente
no debe definirse ni redefinirse y no debe tener intención de entrar o salir. Esperamos compiladores
para hacer una copia como una matriz regular temporal en la entrada pero no realizar ninguna copia de vuelta al regresar.
Además, una sección de matriz con un subíndice vectorial no puede ser un objetivo de puntero, ya que
permitirles complicaría seriamente el mecanismo que los compiladores de otra manera
Hay que establecer para punteros. Por razones similares, dicha sección de matriz no tiene permitido
ser un archivo interno (Sección 10.6).
Además de los patrones de subscripting regulares e irregulares que acabamos de describir, el intrínseco
La función de desplazamiento circular cshift (Sección 9.15.5) proporciona un mecanismo que manipula la matriz
secciones de forma 'envolvente'. Esto es útil para manejar los límites de ciertos tipos.
de problemas periódicos de la cuadrícula, aunque está sujeto a restricciones similares a las del vector
subíndices Si una matriz v (5) tiene el valor [1,2,3,4,5], entonces cshift (v, 2) tiene el valor
[3,4,5,1,2].
La forma general de un subobjeto es
ref-parte [% ref-parte]. . . [(rango de subcadena)]
donde parte-ref ahora tiene la forma
nombre-parte [(sección-subíndice-lista)]
donde el número de subíndices de sección en cada lista debe ser igual al rango de la matriz
o componente de matriz. Cada subíndice de sección es un subíndice (Sección 7.11), un rango uno
expresión entera (subíndice vectorial) o un triplete-subíndice de la forma
[inferior]: [superior] [: zancada]
donde lower, upper y stride son expresiones enteras escalares. Si se omite menor, el valor predeterminado
valor es el límite inferior para este subíndice de la matriz. Si se omite upper, el valor predeterminado
es el límite superior para este subíndice de la matriz. Si se omite el paso, el valor predeterminado es uno.
La zancada puede ser negativa, por lo que es posible tomar, por ejemplo, los elementos de una fila en
orden inverso especificando una sección como
Página 5
132 Fortran moderno explicado
a (i, 10: 1: -1)
La extensión es cero si zancada> 0 y menor> superior, o si zancada <0 y menor <superior. los
El valor de zancada no debe ser cero.
Normalmente, esperamos que los valores de inferior y superior estén dentro de los límites de
subíndice de matriz correspondiente. Sin embargo, todo lo que se requiere es que cada valor realmente utilizado
seleccionar un elemento está dentro de los límites. Así,
a (1, 2: 11: 2)
está permitido incluso si el límite superior de la segunda dimensión de a es solo 10.
El triplete-subíndice especifica una secuencia de valores de subíndice,
inferior, inferior + zancada, inferior + 2 × zancada, ...
ir lo más lejos posible sin ir más allá de la parte superior (por encima de ella cuando zancada> 0 o por debajo de ella
cuando zancada <0). La longitud de la secuencia para el i-ésimo triplete-subíndice determina el i-ésimo
extensión de la matriz que se forma.
El rango de una referencia parcial con una lista de subíndices de sección es el número de subíndices vectoriales y
subíndice tripletes que contiene. Hasta ahora en esta sección, todos los ejemplos han sido de rango
uno; por el contrario, el elemento de matriz ordinario
a (1,7)
es un ejemplo de una referencia parcial de rango cero, y la sección
a (: 1: 7)
es un ejemplo de una referencia parcial de rango dos. El rango de una referencia parcial sin una lista de subíndices de
sección
es el rango del objeto o componente. Una referencia parcial puede ser una matriz; por ejemplo,
alquitrán% du (2)
para la matriz tar de la Sección 7.11 es una sección de matriz con elementos tar (1,1,1)% du (2),
alquitrán (2,1,1)% du (2), alquitrán (3,1,1)% du (2),. . . . Ser capaz de formar secciones de esta manera desde
Las matrices de tipo derivado, así como seleccionando conjuntos de elementos, es una característica muy útil de
idioma. Un ejemplo más prosaico, dada la especificación
tipo (persona), dimensión (1:50) :: my_group
para la persona tipo de la Sección 2.9, es el subobject my_group% id, que es una matriz de enteros
sección de tamaño 50.
Además, para el caso particular de matrices complejas, se pueden aplicar los selectores re e im
para producir una sección de matriz que comprende la parte real o imaginaria de cada elemento de la matriz.
Por ejemplo,
complejo :: x (n), y (n)
x% im = 2.0 * y% im
Desafortunadamente, no está permitido que más de una referencia parcial sea una matriz; por ejemplo,
no esta permitido escribir
alquitrán% du
! Inválido
para la matriz tar de la Sección 7.11. La razón de esto es que si el tar% du se considerara
una matriz, su elemento (1,2,3,4) correspondería a

Página 6
Funciones de matriz 133
alquitrán (2,3,4)% du (1)
lo cual sería una notación demasiado confusa.
La referencia parcial con rango distinto de cero determina el rango y la forma del subobjeto. Si alguno de
su extensión es cero, el subobjeto tiene tamaño cero. Se llama una sección de matriz si el final
parte-ref tiene una sección-subíndice-lista u otra parte-ref tiene un rango distinto de cero.
Un rango de subcadena puede estar presente solo si la última parte-ref es de tipo carácter y es
un escalar o tiene una lista de subíndices de sección. Por convención, el objeto resultante se llama una sección
en lugar de una subcadena. Se forma a partir de la sección no calificada tomando la especificada
subcadena de cada elemento. Tenga en cuenta que, si c es una matriz de caracteres de rango uno,
c (i: j)
es la sección formada por los elementos i a j; si se desean subcadenas de todos los elementos de la matriz,
podemos escribir la sección
c (:) (k: l)
Una sección de matriz que termina con un nombre de componente también se denomina componente de estructura.
Tenga en cuenta que si el componente es escalar, la sección no puede ser calificada por una lista de subíndice final
o lista de subíndices de sección. Por lo tanto, utilizando el ejemplo de la Sección 7.11,
alquitrán% u
es una sección de matriz y
alquitrán (1, 2, 3)% u
es un componente de un elemento válido de tar. La forma
tar% u (1, 2, 3)! no permitido
No se permite.
Además, un nombre de parte a la derecha de una referencia de parte con rango distinto de cero no debe tener
El atributo asignable o puntero. Esto se debe a que tal objeto representaría
una matriz cuyos elementos fueron asignados independientemente y requerirían una muy diferente
mecanismo de implementación del que se necesita para una matriz ordinaria. Por ejemplo, considere
la matriz
tipo (entrada), dimensión (n) :: filas! n de tipo entero
para la entrada de tipo definida en la Figura 2.3. Si se nos permitiera escribir las filas de objeto% siguiente,
se interpretaría como otra matriz de tamaño ny entrada de tipo, pero es probable que sus elementos
para ser almacenado sin ningún patrón regular (cada uno de ellos ha sido almacenado por separado por
asignar declaración) y, de hecho, algunos serán nulos si alguno de los punteros se disocia.
Tenga en cuenta que no hay ningún problema al acceder a punteros individuales como las filas (i)% a continuación.
7.13 Matrices de punteros
Aunque las matrices de punteros como tales no están permitidas en Fortran, el efecto equivalente puede ser
logrado mediante la creación de un tipo que contiene un componente puntero. Esto es útil al construir
Una lista vinculada que es más complicada que la cadena descrita en la Sección 2.12. Por ejemplo,
Si se necesita un número variable de enlaces en cada entrada, la entrada de tipo recursivo de la Figura 2.3
podría expandirse al par de tipos:

Página 7
134 Fortran moderno explicado
tipo ptr
tipo (entrada), puntero :: punto
tipo final ptr
tipo de entrada
real
:: valor
entero
:: índice
tipo (ptr), puntero
:: niños(:)
entrada de tipo final
Después de las asignaciones apropiadas y las asociaciones de punteros, es posible consultar el índice
del niño j del nodo como
nodo% hijos (j)% punto% índice
Este nivel adicional de indirección es necesario porque los elementos individuales de los niños
ellos mismos no tienen el atributo de puntero; esta es una propiedad solo de toda la matriz.
Por ejemplo, podemos tomar dos nodos existentes, digamos ayb, cada uno de los cuales es una raíz de árbol, y
hacer un gran árbol así
árbol% hijos (1)% punto => a
árbol% hijos (2)% punto => b
que no sería posible con la entrada de tipo original.
7.14 Punteros como alias
Si una sección de matriz sin subíndices vectoriales, como
tabla (m: n, p: q)
se desea con frecuencia mientras que las variables enteras m, n, p y q no cambian sus valores, es
conveniente poder referirse a la sección como una matriz con nombre como
ventana
Dicha instalación se proporciona en Fortran mediante punteros y la declaración de asignación de puntero. Aquí,
ventana se declararía así
real, dimensión (:, :), puntero :: ventana
y asociado con la tabla, que por supuesto debe tener el atributo target o puntero, 4 por
la ejecución de la declaración
ventana => tabla (m: n, p: q)
Si, más adelante, el tamaño de la ventana necesita ser cambiado, todo lo que se necesita es otro puntero
sentencia de asignación. Sin embargo, tenga en cuenta que los límites del subíndice para la ventana en este ejemplo
son (1: n-m + 1, 1: q-p + 1) ya que son las proporcionadas por las funciones lbound y ubound
(Sección 9.14.2).
La instalación proporciona un mecanismo para suscribir o seccionar matrices como
4 Laconstrucción asociada (Sección 15.6) proporciona un medio para lograr esto en un alcance limitado sin la necesidad
para el atributo de destino o puntero.

Página 8
Características de la matriz 135
alquitrán% u
donde tar es una matriz yu es un componente escalar, discutido en la Sección 7.11. Aquí podemos
realizar la asociación del puntero
taru => tar% u
si taru es un puntero de rango tres del tipo apropiado. Suscripción como en
taru (1, 2, 3)
entonces está permitido. Aquí los límites del subíndice para taru serán los de tar.
7.15 Asignación de puntero
Hay otras dos instalaciones relacionadas con la instrucción de asignación de puntero de matriz. El primero
es que es posible establecer los límites inferiores deseados en cualquier valor. Esto puede ser deseable en
situaciones como las siguientes. Considerar
real, target :: annual_rainfall (1700: 2003)
real, puntero :: rp1 (:), rp2 (:)
...
rp1 => annual_rainfall
rp2 => annual_rainfall (1800: 1856)
Los límites de rp1 serán (1700: 2003); sin embargo, los de rp2 serán (1:57). Ser capaz
para que un puntero a una subsección de una matriz tenga los límites apropiados, se pueden establecer en
la asignación del puntero de la siguiente manera:
rp2 (1800 :) => annual_rainfall (1800: 1856)
Esta declaración establecerá los límites de rp2 en (1800: 1856).
La segunda facilidad para la asignación del puntero de matriz es que el objetivo de un multidimensional
El puntero de matriz puede ser unidimensional o simplemente contiguo (Sección 7.18.2). La sintaxis es
similar a la especificación de límites inferiores anterior, excepto que en este caso uno especifica
cada límite superior, así como cada límite inferior. Los elementos del puntero de matriz, en matriz
orden de elementos, están asociados con los elementos principales de la matriz de destino. Esto puede ser usado,
por ejemplo, para proporcionar un puntero a la diagonal de una matriz:
real, puntero :: base_array (:), matriz (:, :), diagonal (:)
asignar (base_array (n * n))
matriz (1: n, 1: n) => matriz_base
diagonal => base_array (:: n + 1)
Después de la ejecución de las asignaciones de puntero, diagonal ahora es un puntero a la diagonal
elementos de matriz.
7.16 Constructores de matrices
La sintaxis que presentamos en la Sección 2.10 para las constantes de matriz se puede usar para construir
matrices más generales de rango uno. La forma general de un constructor de matrices es

Página 9
136 Fortran moderno explicado
(/ [type-spec ::] array-constructor-value-list /)
o
[[type-spec ::] array-constructor-value-list]
donde cada valor de constructor de matriz es uno de expr o constructor-implied-do, y el tipo-
spec (si aparece) es el nombre del tipo seguido de los valores del parámetro de tipo entre paréntesis, si
cualquiera, para ambos tipos intrínsecos y derivados. La forma con corchetes es para facilitar
hacer coincidir los paréntesis; tenga en cuenta que no puede mezclarlos, por lo que (/ ...] y [... /) no están permitidos.
La matriz así construida es de rango uno con su secuencia de elementos formados a partir de
secuencia de expresiones escalares y elementos de las expresiones de matriz en orden de elementos de matriz.
Un constructor-implícito-do tiene la forma
(lista-valor-constructor de matriz, variable = expr 1 , expr 2 [, expr 3 ])
donde variable es una variable escalar entera con nombre, y expr 1 , expr 2 y expr 3 son escalares
expresiones enteras Su interpretación es como si la lista de valores del constructor de la matriz se hubiera escrito
max ((expr 2 −expr 1 + expr 3 ) ÷ expr 3 , 0)
veces, con la variable reemplazada por expr 1 , expr 1 + expr 3 , ..., en cuanto a la construcción do (Sec-
sección 4.4). Un ejemplo simple es
(/ (i, i = 1,10) /)
que es igual a
(/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /)
Tenga en cuenta que la sintaxis permite anidar un constructor-implied-do dentro de otro, como en el
ejemplo
(/ ((i, i = 1,3), j = 1,3) /)
que es igual a
(/ 1, 2, 3, 1, 2, 3, 1, 2, 3 /)
y el anidamiento de constructores de estructuras dentro de constructores de matrices (y viceversa); para
instancia, para el tipo en la Sección 7.5,
(/ (matriz (0.0), i = 1, límite) /)
La secuencia puede estar vacía, en cuyo caso se construye una matriz de tamaño cero. El alcance
de la variable es el constructor-implicado-do. Otras declaraciones, o incluso otras partes de la
constructor de matriz, puede referirse a otra variable que tenga el mismo nombre. El valor del otro
la variable no se ve afectada por la ejecución del constructor de matrices y está disponible excepto dentro de
constructor-implícito-do.
Se puede construir una matriz de rango superior a uno a partir de un constructor de matriz usando
la función intrínseca remodelar (Sección 9.15.3). Por ejemplo,
remodelar (fuente = [1,2,3,4,5,6], forma = [2,3])
tiene el valor
135
246

Página 10
Funciones de matriz 137
Si el constructor de matrices no comienza con type-spec ::, sus parámetros de tipo y tipo son
los del primer expr, y cada expr debe tener el mismo tipo y parámetros de tipo. Si cada
expr, expr 1 , expr 2 y expr 3 es una expresión constante (Sección 8.4), el constructor de matriz es
Una expresión constante.
Si un constructor de matriz comienza con type-spec ::, sus parámetros de tipo y tipo son aquellos
especificado por la especificación de tipo. En este caso, los valores del constructor de matriz pueden tener cualquier tipo
y parámetros de tipo (incluida la longitud de caracteres) que son compatibles con la asignación
tipo especificado y parámetros de tipo, y los valores se convierten a ese tipo por el habitual
conversiones de asignaciones.
Aquí hay unos ejemplos:
[personaje (len = 33) :: 'lo bueno', 'lo malo', 'y', &
'la apariencia desafiada']
[complejo (tipo (0d0)) :: 1, (0,1), 3.14159265358979323846264338327d0]
[matriz (kind = kind (0.0), n = 10, m = 20) ::]! matriz de tamaño cero
7.17 El constructo concurrente
Se proporciona una forma adicional de la construcción do, la construcción concurrente do, para ayudar a mejorar
rendimiento al permitir la ejecución paralela de las iteraciones de bucle. La idea básica es que
Al usar esta construcción, el programador afirma que no hay interdependencias entre
iteraciones de bucle. El efecto es similar al de varias directivas específicas del compilador, como
'! dec $ ivdep'; tales directivas han estado disponibles durante mucho tiempo, pero a menudo tienen un poco
diferentes significados en diferentes compiladores.
El uso de do concurrent tiene una larga lista de requisitos que se pueden agrupar en
'limitaciones' sobre lo que puede aparecer dentro del constructo y 'garantías' por parte del programador
que el cálculo tiene ciertas propiedades (esencialmente, sin dependencias) que permiten
paralelización Tenga en cuenta que en este contexto la paralelización no necesariamente requiere múltiples
procesadores, o incluso si hay varios procesadores disponibles, que se utilizarán: otro
estas propiedades también permiten las optimizaciones que mejoran el rendimiento de subprocesos simples,
incluyendo vectorización, canalización y otras posibilidades para superponer la ejecución de
instrucciones de más de una iteración en un solo procesador.
La forma de la declaración concurrente do es
do [,] concurrent ([type-spec ::] index-spec-list [, scalar-mask-expr])
donde type-spec (si está presente) especifica el tipo y tipo de las variables de índice, y index-
spec-list es una lista de especificaciones de índice del formulario
nombre-variable-índice = valor-inicial: valor-final [: valor-paso]
como en
hacer concurrente (i = 1: n, j = 1: m)
Cada nombre de variable de índice es local para el bucle, por lo que no tiene efecto en ninguna variable con el
mismo nombre que podría existir fuera del ciclo; sin embargo, si se omite type-spec, tiene el tipo

Página 11
138 Modern Fortran explicado
y amable que tendría si fuera una variable así. En cualquier caso, debe ser escalar y tener
tipo entero Cada valor inicial, valor final y valor de paso es una expresión entera escalar.
El scalar-mask-expr opcional es de tipo lógico; si aparece, solo esas iteraciones que
cumplir la condición se ejecutan. Es decir,
hacer concurrente (i = 1: n, j = 1: m, i / = j)
...
fin hacer
tiene exactamente el mismo significado que
hacer concurrente (i = 1: n, j = 1: m)
si (i / = j) entonces
...
terminara si
fin hacer
Un ejemplo simple de una construcción simultánea do es
hacer concurrente (i = 1: n)
a (i, j) = a (i, j) + alfa * b (i, j)
fin hacer
Los siguientes elementos están prohibidos dentro de una construcción simultánea do (y el compilador
se requiere para detectar estos, excepto para advance =):
• una declaración que terminaría la construcción concurrente do: es decir, un retorno
declaración (Sección 5.8), una rama (por ejemplo, ir a o err =) con una etiqueta que es
fuera de la construcción, una declaración de salida que saldría del concurrente
construcción, o una declaración de ciclo que nombra una construcción externa do;
• una declaración de control de imagen (Capítulo 17);
• una referencia a un procedimiento que no es puro (Sección 7.8);
• una referencia a uno de los procedimientos ieee_get_flag, ieee_set_halting_mode,
o ieee_get_halting_mode del módulo intrínseco ieee_exceptions (Sec-
ción 18.8); y
• una declaración de entrada / salida con un avance = especificador (Sección 10.11).
Todo lo anterior está prohibido porque son imposibles o extremadamente difíciles de
use sin romper la regla 'no interdependencias entre iteraciones'.
Al usar do concurrent, el programador garantiza que la ejecución de las iteraciones de bucle en
un orden diferente no cambiaría los resultados (excepto posiblemente por el orden de salida de registros
a un archivo secuencial); en particular:
• cualquier variable referenciada se definió previamente en la misma iteración o su valor es
no afectado por ninguna otra iteración;
• cualquier puntero al que se haga referencia ya sea un puntero asociado previamente en el mismo
iteración, o no tiene su asociación de puntero cambiada por ninguna otra iteración;

Pagina 12
Características de matriz 139
• no se utilizará ningún objeto asignable asignado o desasignado por una iteración 5
por cualquier otra iteración, a menos que cada iteración que usa el objeto primero lo asigne y
finalmente lo desasigna;
• los registros (o posiciones) en un archivo no están escritos por una iteración y leídos de nuevo por
otra iteración (Capítulo 10).
Si los registros se escriben en un archivo secuencial (Capítulo 10) por más de una iteración de
bucle, el orden entre los registros escritos por diferentes iteraciones es indeterminado. Ese
es decir, los registros escritos por una iteración pueden aparecer antes que los registros escritos por la otra,
después de los registros escritos por el otro, o se intercalan.
Además, cuando la ejecución de la construcción se ha completado,
• cualquier variable cuyo valor se vea afectado por más de una iteración queda indefinido en
terminación del bucle; y
• cualquier puntero cuyo estado de asociación cambie en más de una iteración tiene un
estado de asociación de indefinido.
Tenga en cuenta que cualquier bucle do normal que satisfaga las limitaciones y que obviamente tenga el
las propiedades requeridas se pueden paralelizar, por lo que el uso de do concurrent no es necesario para paralelo
ejecución. De hecho, un compilador que paraleliza hacer concurrente es probable que lo trate como una solicitud
que debería paralelizar ese ciclo; Si el recuento de iteraciones de bucle es muy pequeño, esto podría resultar en
peor rendimiento que un bucle do normal debido a la sobrecarga de iniciar hilos paralelos
de ejecución Por lo tanto, incluso cuando las garantías proporcionadas por el programador se derivan trivialmente
desde el propio cuerpo del bucle, hacer concurrente sigue siendo útil para
• indicando al compilador que es probable que tenga un recuento de iteraciones lo suficientemente alto como para
hacer que la paralelización valga la pena;
• usar el compilador para hacer cumplir las prohibiciones (por ejemplo, no hacer llamadas a procedimientos impuros);
• documentar la paralelización para la lectura y mantenimiento de códigos; y
• como una muleta para compiladores cuyas capacidades de análisis son limitadas.
7.18 Características orientadas al rendimiento
7.18.1 El atributo contiguo
Se espera que la mayoría de las matrices se mantengan en memoria contigua, pero hay excepciones
como estas secciones de matriz:
vector (:: 2)
! todos los elementos impares
vector (10,1, -1)! orden inverso
cxarray% re
! las partes reales de una matriz compleja
(donde la tercera línea usa la sintaxis de la Sección 2.9). Un puntero o matriz de forma asumida que
no es contiguo puede producirse por asociación con una sección de matriz que no es contigua,
y el compilador tiene que permitir esto. El atributo contiguo es un atributo para puntero y
matrices ficticias de forma asumida. Para un puntero de matriz, restringe su objetivo a ser contiguo.
5 Es decir, referenciada, definida, asignada, desasignada o sobre la que se consulta cualquier propiedad dinámica.

Página 13
140 Fortran moderno explicado
Para una matriz de forma asumida, especifica que si el argumento real correspondiente no es
contigua, la copia de copia de salida se utiliza para hacer que el argumento ficticio sea contiguo.
Saber que una matriz es contigua en este sentido simplifica el recorrido de la matriz y la matriz
cálculos de direcciones de elementos, que potencialmente mejoran el rendimiento. Si esta mejora
es significativo depende de la fracción de tiempo que se dedica a realizar el recorrido y la dirección
operaciones de cálculo; en algunos programas esta vez es sustancial, pero en muchos casos es
insignificante en primer lugar.
Tradicionalmente, el estándar Fortran ha evitado especificar si las matrices son
contiguo en el sentido de ocupar ubicaciones de memoria secuenciales sin intervenir
espacios desocupados. En el pasado, esta tradición ha permitido el multiprocesador de alto rendimiento
implementaciones del lenguaje, pero el atributo contiguo es un movimiento hacia más
limitaciones específicas de hardware. Aunque las matrices contiguas se describen solo en términos de
restricciones de idioma y no en términos del hardware de memoria, la interacción entre estos
e interoperabilidad con el lenguaje C (Capítulo 19) significa que estas matrices casi
sin duda se almacenará en ubicaciones de memoria contiguas.
Cualquiera de las siguientes matrices se considera contigua por el estándar:
• una matriz con el atributo contiguo;
• una matriz completa (matriz con nombre o componente de matriz sin calificación adicional) que es
no un puntero o una forma asumida;
• una matriz de forma asumida que es un argumento asociado con una matriz que es contigua;
• una matriz asignada por una instrucción de asignación;
• un puntero asociado con un objetivo contiguo; o
• una sección de matriz de tamaño distinto de cero siempre que
- su objeto base es contiguo;
- no tiene un subíndice vectorial;
- los elementos de la sección, en orden de elementos de la matriz, son elementos del objeto base
que son consecutivos en orden de elemento de matriz;
- si la matriz es de tipo carácter y aparece un selector de subcadena, el selector
especifica todos los caracteres de la cadena;
- no es un componente de una matriz; y
- no es la parte real o imaginaria de una matriz de tipo complejo.
Un subobjeto (de una matriz) definitivamente no es contiguo si se aplican todas estas condiciones:
• it (el subobject) tiene dos o más elementos;
• sus elementos en orden de elementos de la matriz no son consecutivos en los elementos del original
formación;
• no es una matriz de caracteres de longitud cero; y
• no es de un tipo derivado sin componentes finales que no sean matrices de tamaño cero y
cadenas de caracteres de longitud cero.
Si una matriz que no está en ninguna de las listas es contigua o no es específica del compilador.
El atributo contiguo se puede especificar con la palabra clave contigua en un tipo
declaración de declaración, por ejemplo

Página 14
Funciones de matriz 141
subrutina s (x)
real, contigua :: x (:, :)
real, puntero, contiguo :: columna (:)
También se puede especificar mediante la declaración contigua, que tiene la forma
contigua [::] nombre-objeto-lista
La contigüidad se puede probar con la función de consulta is_contiguous (Sección 9.14.1).
Figura 7.10 Uso de is_contiguous antes de usar c_loc.
proceso de subrutina (x)
real (c_float), target :: x (:)
interfaz
subrutina c_rutina (a, nbytes)
use iso_c_binding
tipo (c_ptr), valor
:: una
entero (c_size_t), valor :: nbytes
subrutina final
interfaz final
...
if (is_contiguous (x)) entonces
llame a c_routine (c_loc (x), c_sizeof (x))
más
detener 'x necesita ser contiguo'
terminara si
subrutina final
Las matrices en C siempre son contiguas, por lo que se hace referencia a la función intrínseca c_loc (Sec-
La sección 19.3) está permitida para cualquier objetivo que sea contiguo (en tiempo de ejecución). El ejemplo
en la Figura 7.10 usa is_contiguous para verificar que se le está pidiendo que procese un contiguo
objeto, y produce un mensaje de error si no es así. También hace uso de la función c_sizeof
para calcular el tamaño de x en bytes (consulte la Sección 19.7).
También existe el concepto de simplemente contiguo; es decir, no solo el objeto es contiguo,
pero puede verse que obviamente es así en el momento de la compilación. A diferencia de 'ser contiguo', esto es
completamente estandarizado Esto se discute más a fondo en la siguiente sección.
Cuando se trata de matrices contiguas de forma asumida y punteros de matriz, es importante
para tener en cuenta los diversos requisitos y restricciones de tiempo de ejecución. Para forma asumida
matrices, el atributo contiguo no hace más requisitos en el programa: si el real
el argumento no es contiguo, se realiza una copia local al ingresar al procedimiento y cualquier cambio
a su valor se copian de nuevo al argumento real al salir. Dependiendo del número y
manera de las referencias a la matriz en el procedimiento, el costo de la copia puede ser mayor que
cualquier supuesto ahorro de rendimiento dado por el atributo contiguo. Por ejemplo, en
función compleja f (v1, v2, v3)
real, contigua, intento (in) :: v1 (:), v2 (:), v3 (:)
f = cmplx (suma (v1 * v2 * v3)) ** (- tamaño (v1))
función final
Página 15
142 Fortran moderno explicado
dado que solo se accede a las matrices una vez, si algún argumento real no es contiguo, esto
casi con certeza funcionan mucho peor que si el atributo contiguo no estuviera presente.
Para punteros de matriz, el atributo contiguo tiene un requisito de tiempo de ejecución para que sea
asociado solo con un objetivo contiguo (mediante asignación de puntero). Sin embargo, es el
la responsabilidad del programador de verificar esto, o de "saber" que el puntero nunca se convertirá
asociado con una sección no contigua. (Tal conocimiento es propenso a volverse falso en el
curso de mantenimiento del programa, por lo que se recomienda verificar cada asignación de puntero).
Comentarios similares se aplican al uso de la función c_loc en una matriz que podría no ser
contiguo. Si se violan estos requisitos, es casi seguro que el programa producirá
respuestas incorrectas sin indicación de la falla.
7.18.2 Designadores de matriz simplemente contiguos
Un designador de matriz simplemente contiguo es, en principio, un designador que no solo describe un
matriz (o sección de matriz) que es contigua, pero que se puede ver fácilmente en el momento de la compilación
ser contiguo Si un designador es simplemente contiguo no depende del valor de
cualquier variable
Una matriz simplemente contigua se puede usar de las siguientes maneras:
• como el objetivo de una asignación de puntero de reasignación de rango (es decir, asociar un puntero con
un objetivo de un rango diferente, ver Sección 7.15);
• como un argumento real correspondiente a un argumento ficticio que no se supone
matriz de forma o que es una matriz de forma supuesta con el atributo contiguo, cuando
ambos tienen el atributo asíncrono o volátil;
• como un argumento real correspondiente a un puntero ficticio con el atributo contiguo
(esto también requiere que el argumento real tenga el puntero o el atributo de destino).
El ejemplo en la Figura 7.11 'aplana' la matriz a en un vector simple, y luego usa eso
asociar otro puntero con la diagonal de la matriz.
Figura 7.11 Diagonal de la matriz contigua.
real, objetivo :: a (n, m)
real, puntero :: a_flattened (:), a_diagonal (:)
a_ aplanado (1: n * m) => a
a_diagonal
=> a_ aplanado (:: n + 1)
En la Figura 7.12, se debe evitar la copia en la llamada de start_bufferin porque
iniciará una operación de entrada asíncrona para leer valores en la matriz y la lectura
Continuar después del regreso. Debido a que tanto x como y son simplemente contiguos, la copia de copia es
evitado
Otro ejemplo del uso de simplemente contiguo para hacer cumplir la contigüidad de un
El argumento se explica en la Sección 7.18.3.
Además, para la asociación de argumentos con una matriz ficticia (ver Sección 17.9) que es una matriz
con el atributo contiguo o una matriz que no tiene forma asumida, el argumento real
se requiere que sea simplemente contiguo para evitar cualquier posibilidad de copia en copia

Página 16
Características de matriz 143
Figura 7.12 Búfer contiguo para entrada / salida asíncrona. La entrada / salida asincrónica es
descrito en la Sección 10.15.
interfaz
subrutina start_bufferin (a, n)
entero, intento (in)
:: n
real, intento (fuera), asíncrono :: a (n)
subrutina final
interfaz final
real, asíncrono :: x (n), y (n)
...
llamar a start_bufferin (x)
...
llamar a start_bufferin (y)
ocurriendo. Desafortunadamente, el estándar Fortran no requiere la detección de la violación de
esta regla, lo que significa que un programa que lo rompe puede fallar o producir respuestas incorrectas
sin ninguna advertencia
Además, cuando una matriz simplemente contigua con el atributo de destino y no el atributo de valor
(Sección 19.8) se utiliza como argumento real correspondiente a un argumento ficticio que tiene
el atributo de destino y es una matriz de forma asumida con el atributo contiguo o es un
matriz de forma explícita,
• un puntero asociado con el argumento real se asocia con el ficticio
argumento sobre la invocación del procedimiento; y
• cuando finaliza la ejecución del procedimiento, punteros en otros ámbitos que fueron
asociados con el argumento ficticio están asociados con el argumento real.
Sin embargo, no recomendamos utilizar este hecho complicado, ya que es difícil de entender.
y es muy probable que el mantenimiento del programa rompa una de las condiciones esenciales para su
aplicabilidad.
Un designador de matriz es simplemente contiguo si y solo si es
• una matriz completa que tiene el atributo contiguo;
• una matriz completa que no es una matriz de forma supuesta o un puntero de matriz; o
• una sección de una matriz simplemente contigua que
- no es la parte real o imaginaria de una matriz compleja (ver Sección 2.9);
- no tiene un selector de subcadena;
- no es un componente de una matriz; y
- o no tiene una sección-subíndice-lista, o tiene una sección-subíndice-lista que
especifica una sección simplemente contigua.
Una sección-subíndice-lista especifica una sección simplemente contigua si y solo si
• no tiene un subíndice vectorial;

Página 17
144 Fortran moderno explicado
• todos menos el último subíndice triplete son dos puntos;
• el último triplete de subíndice no tiene un paso; y
• ningún subíndice-triplete está precedido por una sección-subíndice que es un subíndice.
Una variable de matriz es simplemente contigua si y solo si es una matriz simplemente contigua
designador o una referencia a una función que devuelve un puntero con el atributo contiguo.
7.18.3 Orientación automática del puntero
Se permite que un argumento real con el atributo objetivo corresponda a un puntero ficticio
con la intención en atributo. Esto se ilustra en la figura 7.13; en este caso, la automática
Figura 7.13 Cómoda orientación automática. El atributo protegido se describe en
Sección 8.6.2.
módulo m
real, puntero, protegido :: parameter_list (:)
contiene
subrutina set_params (lista)
real, puntero, intento (in) :: lista (:)
parameter_list => list
subrutina final
...
módulo final
...
resolución de subrutina (problema, argumentos)
usar m
real, target :: args (:)
...
llamar a set_params (args)
...
subrutina final
la focalización solo se usa por conveniencia, simplemente ahorrando la molestia de crear un local
puntero, apuntando a args y pasando el puntero local a set_params.
Sin embargo, la orientación automática también se puede utilizar para hacer cumplir los requisitos de contigüidad; si un
el puntero ficticio tiene el atributo contiguo, el argumento real debe ser simplemente contiguo
(Ver Sección 7.18.2). Esto significa que el usuario puede estar seguro de que no hay copias no deseadas, por
Se está llevando a cabo un mecanismo de paso de argumentos copia-entrada-copia. Esto es ilustrado por
Figura 7.14, que requiere una matriz contigua para ser utilizada para operaciones de almacenamiento en búfer. Una
llamada
set_buffer con un argumento que no es simplemente contiguo produciría un error en
tiempo de compilación.

Página 18
Funciones de matriz 145
Figura 7.14 Orientación automática de la matriz contigua.
módulo buffer_control
carácter (:), contiguo, puntero, protegido :: buffer (:)
contiene
subrutina set_buffer (charbuf)
carácter (*), puntero, intento (in), contiguo :: charbuf (:)
buffer => charbuf
subrutina final
módulo final
...
carácter, asignable, objetivo :: mybuf (:)
...
asignar (mybuf (n))
llamar a set_buffer (mybuf)
7.19 Resumen
Hemos explicado que las matrices pueden tener un tamaño cero y que no se necesitan reglas especiales para
ellos. El almacenamiento para una matriz se puede asignar automáticamente al ingresar a un procedimiento y
automáticamente desasignado al regreso. Las funciones se pueden valorar a través de la matriz
mecanismo de una referencia elemental que realiza el mismo cálculo para cada matriz
elemento, o a través de la función verdaderamente con valor de matriz. Los procedimientos elementales pueden ser puros
o
impuro. Las asignaciones de matriz se pueden enmascarar mediante el uso de la instrucción where y
construir. Los componentes de estructura pueden ser matrices si el padre es una matriz o el componente
es una matriz, pero no ambas. Una submatriz puede formularse directamente como una sección de matriz,
o indirectamente usando la asignación del puntero para asociarlo con un puntero. Una matriz puede ser
construido a partir de una secuencia de expresiones. Se puede usar una matriz lógica como máscara.
Las funciones intrínsecas son una parte importante de las características de la matriz y se describirán en
Capítulo 9.
Concluimos este capítulo con un programa completo, véanse las Figuras 7.15 y 7.16, que
ilustra el uso de expresiones de matriz, asignaciones de matriz, matrices asignables, automático
matrices y secciones de matrices. El módulo lineal contiene una subrutina para resolver un conjunto de
ecuaciones lineales, y esto se llama desde un programa principal que le indica al usuario el problema
y luego lo resuelve

Página 19
146 Modern Fortran explicado
Figura 7.15 Primera parte de un módulo para resolver un conjunto de ecuaciones lineales; el tamaño se describe en
La Sección 9.14.2 y maxloc se describen en la Sección 9.16.
módulo lineal
entero, parámetro, public :: kind = selected_real_kind (10)
public :: resolver
contiene
resolución de subrutina (a, piv_tol, b, ok)
! argumentos
real (kind), intent (inout), dimension (:, :) :: a
! La matriz a.
real (kind), intent (in) :: piv_tol
! El pivote más pequeño aceptable.
real (kind), intent (inout), dimension (:) :: b
! El vector del lado derecho en
! entrada. Sobrescrito por la solución.
lógica, intención (fuera)
:: Okay
! Es cierto después de una entrada exitosa
! y falso de lo contrario.
! Variables locales
entero :: i
! Índice de fila.
entero :: j
! Índice de columna.
entero :: n
! Orden matricial.
real (tipo), dimensión (tamaño (b)) :: fila
! Matriz automática necesaria para el espacio de trabajo;
real (tipo) :: elemento! Variable del espacio de trabajo.
n = tamaño (b)
ok = tamaño (a, 1) == n. y. tamaño (a, 2) == n
si (.not.ok) entonces
regreso
terminara si
hacer j = 1, n
!
Actualizar elementos en la columna j.
do i = 1, j - 1
a (i + 1: n, j) = a (i + 1: n, j) - a (i, j) * a (i + 1: n, i)
fin hacer
!
Encuentra pivote y verifica su tamaño
i = maxloc (abs (a (j: n, j)), dim = 1) + j - 1
if (abs (a (i, j)) <piv_tol) entonces
ok = falso.
regreso
terminara si

Página 20
Características de matriz 147
Figura 7.16 Segunda parte del módulo de la Figura 7.15 y un programa que lo utiliza. La edición
Los descriptores utilizados en las declaraciones de escritura se describen en el Capítulo 11.
!
Si es necesario, aplique el intercambio de filas
si (i / = j) entonces
fila = a (j, :); a (j, :) = a (i, :); a (i, :) = fila
elemento = b (j); b (j) = b (i); b (i) = elemento
terminara si
!
Calcule los elementos j + 1: n de la columna j.
a (j + 1: n, j) = a (j + 1: n, j) / a (j, j)
fin hacer
! Sustitución hacia adelante
do i = 1, n-1
b (i + 1: n) = b (i + 1: n) - b (i) * a (i + 1: n, i)
fin hacer
!
Sustitución de la espalda
hacer j = n, 1, -1
b (j) = b (j) / a (j, j)
b (1: j-1) = b (1: j-1) - b (j) * a (1: j-1, j)
fin hacer
final subrutina resolver
módulo final lineal
programa principal
usar lineal
entero :: i, n
real (kind), asignable :: a (:, :), b (:)
lógico :: ok
print *, '¿Orden de matriz?'
leer *, n
asignar (a (n, n), b (n))
do i = 1, n
escriba (*, '(a, i2, a)') 'Elementos de la fila', i, 'de a?'
leer *, a (i, :)
escribir (*, '(a, i2, a)') 'Componente', i, 'de b?'
leer *, b (i)
fin hacer
llamar a resolver (a, maxval (abs (a)) * 1.0e-10, b, ok)
si (ok) entonces
write (*, '(/,a,/,(5f12.4))') 'La solución es', b
más
print *, 'La matriz es singular'
terminara si
final del programa principal

Página 21
148 Fortran moderno explicado
Ejercicios
1. Dada la declaración de matriz
real, dimensión (50,20) :: a
escribir secciones de matriz que representan
i) la primera fila de a;
ii) la última columna de a;
iii) cada segundo elemento en cada fila y columna;
iv) como para (iii) en orden inverso en ambas dimensiones;
v) una matriz de tamaño cero.
2. Escriba una instrucción where para duplicar el valor de todos los elementos positivos de una matriz z.
3. Escriba una declaración de matriz para una matriz j que se definirá completamente por la instrucción
j = (/ (3, 5, i = 1,5), 5,5,5, (i, i = 5,3, -1) /)
4. Clasifique las siguientes matrices:
Ejemplo de subrutina (n, a, b)
real, dimensión (n, 10) :: w
real
:: a (:), b (0 :)
real, puntero
:: d (:, :)
5. Escriba una declaración y una declaración de asignación de puntero adecuada para hacer referencia como una matriz todo el
tercer
elementos del componente du en los elementos de la matriz tar que tienen los tres valores de subíndice incluso
(Sección 7.11).
6. Dadas las declaraciones de matriz
entero, dimensión (100, 100), objetivo :: l, m, n
entero, dimensión (:, :), puntero
:: ll, mm, nn
reescribir las declaraciones
l (j: k + 1, j-1: k) = l (j: k + 1, j-1: k) + l (j: k + 1, j-1: k)
l (j: k + 1, j-1: k) = m (j: k + 1, j-1: k) + n (j: k + 1, j-1: k) + n (j: k +1, j: k + 1)
como podrían aparecer después de la ejecución de las declaraciones
ll => l (j: k + 1, j-1: k)
mm => m (j: k + 1, j-1: k)
nn => n (j: k + 1, j-1: k)
7. Complete el Ejercicio 1 del Capítulo 4 usando la sintaxis de matriz en lugar de hacer construcciones.
8. Escriba un módulo para mantener una estructura de datos que consista en una lista vinculada de enteros, con la capacidad de
agregar y eliminar miembros de la lista, de manera eficiente.
9. Escriba un módulo que contenga el ejemplo de la Figura 7.5 (Sección 7.5) como un procedimiento de módulo y
admite las operaciones y asignaciones definidas que contiene.

Página 22

8. Declaraciones de especificación
8.1 Introducción
En los capítulos anteriores hemos aprendido los elementos del lenguaje Fortran, cómo
puede combinarse en expresiones y asignaciones, cómo podemos controlar el flujo lógico de
un programa, cómo dividir un programa en partes manejables, y han considerado cómo las matrices
puede ser procesado Hemos visto que este conocimiento es suficiente para escribir programas, cuando
combinado con declaraciones rudimentarias de lectura e impresión y con la declaración final.
En los capítulos 2 a 7, encontramos algunas declaraciones de especificación al declarar el tipo y
otras propiedades de los objetos de datos, pero para facilitar la tarea del lector no siempre explicamos
Todas las opciones disponibles. En este capítulo llenamos este vacío. Para empezar, sin embargo, es
necesario para recordar el lugar de las declaraciones de especificación en un lenguaje de programación. UNA
El programa es procesado por una computadora en etapas. En la primera etapa, compilación, la fuente
el código (texto) del programa lo lee un programa conocido como compilador que lo analiza,
y genera archivos que contienen código objeto. Cada unidad de programa del programa completo es
Generalmente procesado por separado. El código objeto es una traducción del código fuente a un formulario.
que puede ser entendido por el hardware de la computadora y contiene las instrucciones precisas como
a qué operaciones debe realizar la computadora. Usando estos archivos, un programa ejecutable es
construido. La etapa final consiste en la ejecución, mediante la cual las instrucciones codificadas son
realizado y los resultados de los cálculos disponibles.
Durante la primera etapa, el compilador requiere información sobre las entidades involucradas.
Esta información se proporciona al comienzo de cada unidad de programa o subprograma por
declaraciones de especificación. La descripción de la mayoría de estos es el tema de este capítulo. los
sentencias de especificación asociadas con interfaces de procedimiento, incluidos bloques de interfaz y
la declaración de la interfaz y también la declaración externa se explicaron en el Capítulo 5. El
La declaración intrínseca se explica en la Sección 9.1.3.
8.2 Escritura implícita
Muchos lenguajes de programación requieren que todas las entidades escritas tengan sus tipos especificados
explícitamente. Cualquier entidad de datos que se encuentre en una instrucción ejecutable sin su tipo
haber sido declarado hará que el compilador indique un error. Fortran también tiene implícito
escribiendo: a una entidad se le asigna un tipo de acuerdo con la letra inicial de su nombre a menos que sea
escrito explícitamente apareciendo en una declaración de declaración de tipo o accediendo por uso o host
asociación. El valor predeterminado es una entidad cuyo nombre comienza con una de las letras i, j, ...,
Fortran moderno explicado, 2da edición. Michael Metcalf, John Reid y Malcolm Cohen. prensa de la Universidad de Oxford
(2018) cG Michael Metcalf, John Reid y Malcolm Cohen 2018. DOI 10.1093 / oso / 9780198811893.001.0001

Página 23
150 Fortran moderno explicado
n es de tipo entero predeterminado y una entidad cuyo nombre comienza con una de las letras a, b, ...,
h, o o, p, ..., z es del tipo real predeterminado. 1
La escritura implícita puede conducir a errores de programa; por ejemplo, si un nombre de variable es mal escrito,
El nombre mal escrito dará lugar a una variable separada que, si se usa, puede conducir a imprevistos.
Consecuencias. Por esta razón, recomendamos evitar la escritura implícita. La declaración
implícito ninguno
evita la escritura implícita en una unidad de alcance. 2 Puede estar precedido dentro de la unidad de alcance solo por
usar (y formatear) declaraciones. Una unidad de alcance sin una declaración implícita tiene el mismo
escritura implícita (o falta de ella) como su host. Por ejemplo, una sola declaración implícita none en
un módulo evita la escritura implícita en el módulo y todas las unidades de alcance que contiene.
8.3 Constantes nombradas
Dentro de un programa, a menudo necesitamos definir una constante o un conjunto de constantes. Por ejemplo, en un
programa que requiere el uso repetido de la velocidad de la luz, podríamos usar una variable real c que es
dado su valor por la declaración
c = 2.99792458
Un peligro en esta práctica es que el valor de c puede sobrescribirse sin darse cuenta, por ejemplo
porque otro programador reutiliza c como una variable para contener una cantidad diferente, no
observe que el nombre ya está en uso.
También puede ser que el programa contenga especificaciones como
real
:: x (10), y (10), z (10)
entero :: mesh (10, 10), ipoint (100)
donde todas las dimensiones son 10 o 10 2 . Dichas especificaciones pueden usarse ampliamente, y 10
incluso puede aparecer como una constante explícita, por ejemplo, como un parámetro en una construcción que procesa
estas matrices:
¿i = 1, 10
Más tarde, puede darse cuenta de que se requiere el valor 20 en lugar de 10, y el nuevo valor debe
sustituirse en todas partes donde ocurra la anterior, una empresa propensa a errores.
Otro caso se encontró en la Sección 2.6, donde se necesitaban constantes con nombre para el tipo amable
valores paramétricos.
Para hacer frente a todas estas situaciones, Fortran contiene lo que se conoce como llamado
constantes Puede que nunca aparezcan en el lado izquierdo de una declaración de asignación, pero pueden
ser usado en expresiones de cualquier manera en que se pueda usar una constante literal. Una declaración de tipo
La declaración puede usarse para especificar una constante de este tipo:
real, parámetro :: c = 2.99792458
El valor está protegido, ya que c es ahora el nombre de una constante y no se puede usar como variable
nombre en la misma unidad de alcance. Del mismo modo, podemos escribir
1 Consulte la Sección A.8 para conocer los medios para especificar otras asignaciones entre las letras y los tipos.
2 Esta declaración se ha mejorado en Fortran 2018, consulte la Sección 23.2.

Página 24
Declaraciones de especificación 151
entero, parámetro :: longitud = 10
real
:: x (longitud), y (longitud), z (longitud)
entero
:: malla (longitud, longitud), ipoint (longitud ** 2)
...
do i = 1, longitud
que tiene la clara ventaja de que para cambiar el valor de 10 a 20 solo una línea
debe modificarse y el nuevo valor se propaga correctamente.
Una constante con nombre puede ser una matriz, como en el caso
real, dimensión (3), parámetro :: campo = [0.0, 10.0, 20.0]
Sin embargo, no es necesario declarar la forma de antemano: la forma puede tomarse del
valor. Esto se llama una matriz de forma implícita y se especifica mediante un asterisco como límite superior,
por ejemplo,
carácter, parámetro :: vocales (*) = ['a', 'e', 'i', 'o', 'u']
Para una matriz de rango superior a uno, la función de remodelación descrita en la Sección 9.15.3 debe
se aplicado. Si la matriz tiene forma implícita, se debe especificar un asterisco para cada límite superior.
Por ejemplo
entero, parámetro :: potencias (0: *, *) = &
remodelar ([0, 1, 2, 3, 0, 1, 4, 9, 0, 1, 8, 27], [4, 3])
declara poderes para tener los límites (0: 3, 1: 3).
Del mismo modo, la longitud de un escalar llamado constante de tipo de carácter puede especificarse como un
asterisco y tomado directamente de su valor, lo que evita la necesidad de contar la longitud de un
cadena de caracteres, haciendo modificaciones a su definición mucho más fácil. Un ejemplo de esto es
carácter (len = *), parámetro :: cadena = 'No es necesario contar'
Desafortunadamente, es necesario contar cuando una matriz de caracteres se define usando un constructor de matrices
sin un especificador de tipo, ya que todos los elementos deben tener la misma longitud:
carácter (len = 7), parámetro, dimensión (3) ::
Y
c = ['Cohen', 'Metcalf', 'Reid
']
no sería correcto sin los dos espacios en blanco en 'Cohen' y los tres en 'Reid
'. Esta
se puede evitar la necesidad utilizando una especificación de tipo, como se muestra en la Sección 7.16; pero eso tiene el
posibilidad de truncamiento si se especifica una longitud incorrecta en la especificación de tipo.
Una constante con nombre puede ser de tipo derivado, como en el caso
tipo (posn), parámetro :: a = posn (1.0,2.0,0)
para el tipo
tipo posn
real
:: x, y
entero :: z
tipo final posn

Página 25
152 Fortran moderno explicado
Tenga en cuenta que un subobjeto de una constante no necesariamente tiene que tener un valor constante. Por ejemplo,
Si i es una variable entera, el campo (i) puede tener el valor 0.0, 10.0 o 20.0. Tenga en cuenta también que
una constante puede no ser un puntero, un objeto asignable, un argumento ficticio o un resultado de función,
ya que estas son siempre variables. Sin embargo, puede ser de un tipo derivado con una asignación
componente que no está asignado o un componente puntero que está disociado. Claramente, porque
dicho componente es parte de una constante, no se permite asignar ni puntero asignado.
El atributo de parámetro es un medio importante por el cual las constantes pueden protegerse de
sobrescritura y programas modificados de forma segura. Debe usarse para estos fines en
Cada ocasión posible.
8.4 Expresiones constantes
En un ejemplo en la sección anterior, la longitud de expresión ** 2 apareció en una de las matrices
especificaciones encuadernadas. Este es un ejemplo particular de una expresión constante, que es un
expresión cuyo valor no puede cambiar durante la ejecución y que se puede verificar en la compilación
hora de cumplir esta regla. El estándar especifica una larga lista de posibilidades para primarias en
expresiones constantes, ver abajo, para que los compiladores puedan realizar esta verificación. Es tan
siempre que si el programador está convencido de que una expresión satisface la regla, es casi seguro
hace.
En la definición de una constante nombrada podemos usar cualquier expresión constante, y el
constante se define con el valor de la expresión de acuerdo con las reglas de intrínseco
asignación. Esto se ilustra con el ejemplo.
entero, parámetro :: longitud = 10, largo = selected_real_kind (12)
real, parámetro
:: lsq = longitud ** 2
Tenga en cuenta de este ejemplo que es posible en una declaración definir varias constantes con nombre,
en este caso dos, separados por comas.
Una expresión constante es una expresión en la que cada operación es intrínseca y cada
primario es
i) una constante o un subobjeto de una constante;
ii) un constructor de matriz en el que cada expresión es una expresión constante;
iii) un constructor de estructuras en el que cada componente asignable es una referencia al
función intrínseca nula, cada componente de puntero es un objetivo de inicialización (Sección
8.5.1) o una referencia a nulo, y cada otro componente es una expresión constante;
iv) una consulta de especificación (Sección 8.18) donde cada argumento de designación o función es
una expresión constante o una variable cuyas propiedades indagadas no se asumen,
diferido o definido por una expresión que no es una expresión constante;
v) una referencia a una función intrínseca elemental o transformacional (Capítulo 9) que no sea
command_argument_count, null, num_images, this_image o transfer proporcionado
cada argumento es una expresión constante;

También podría gustarte