mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-23 17:41:41 +00:00
Compare commits
14 Commits
ae133854e5
...
ab1f3e3a03
Author | SHA1 | Date | |
---|---|---|---|
|
ab1f3e3a03 | ||
|
495272cff9 | ||
|
0c5eb762c4 | ||
|
db551c63ac | ||
|
e346cbded5 | ||
|
74f097c2ca | ||
|
29610d715d | ||
|
35a319b3f7 | ||
|
ac2ada4cc3 | ||
|
122964ebed | ||
|
27de08d069 | ||
|
02ea02e8e8 | ||
|
790fd6ec72 | ||
|
6691524748 |
165
c.html.markdown
165
c.html.markdown
@ -11,6 +11,7 @@ contributors:
|
||||
- ["Joshua Li", "https://github.com/JoshuaRLi"]
|
||||
- ["Dragos B. Chirila", "https://github.com/dchirila"]
|
||||
- ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"]
|
||||
- ["Chris Harding", "https://github.com/sjrct"]
|
||||
---
|
||||
|
||||
Ah, C. Still **the** language of modern high-performance computing.
|
||||
@ -27,7 +28,8 @@ memory management and C will take you as far as you need to go.
|
||||
>
|
||||
> `-Wall -Wextra -Werror -O2 -std=c99 -pedantic`
|
||||
>
|
||||
> For information on what these flags do as well as other flags, consult the man page for your C compiler (e.g. `man 1 gcc`) or just search online.
|
||||
> For information on what these flags do as well as other flags, consult the man
|
||||
> page for your C compiler (e.g. `man 1 gcc`) or just search online.
|
||||
|
||||
```c
|
||||
// Single-line comments start with // - only available in C99 and later.
|
||||
@ -63,26 +65,28 @@ enum days {SUN = 1, MON, TUE, WED = 99, THU, FRI, SAT};
|
||||
// libraries for the headers.
|
||||
// For your own headers, use double quotes instead of angle brackets, and
|
||||
// provide the path:
|
||||
#include "my_header.h" // local file
|
||||
#include "my_header.h" // local file
|
||||
#include "../my_lib/my_lib_header.h" //relative path
|
||||
|
||||
// Declare function signatures in advance in a .h file, or at the top of
|
||||
// your .c file.
|
||||
void function_1();
|
||||
int function_2(void);
|
||||
void function_1(void);
|
||||
int function_2(int a, float b);
|
||||
|
||||
// At a minimum, you must declare a 'function prototype' before its use in any function.
|
||||
// Normally, prototypes are placed at the top of a file before any function definition.
|
||||
// At a minimum, you must declare a 'function prototype' before its use in any
|
||||
// function. Normally, prototypes are placed at the top of a file before any
|
||||
// function definition.
|
||||
int add_two_ints(int x1, int x2); // function prototype
|
||||
// although `int add_two_ints(int, int);` is also valid (no need to name the args),
|
||||
// it is recommended to name arguments in the prototype as well for easier inspection
|
||||
// although `int add_two_ints(int, int);` is also valid (no need to name the
|
||||
// args), it is recommended to name arguments in the prototype as well for
|
||||
// easier inspection
|
||||
|
||||
// Function prototypes are not necessary if the function definition comes before
|
||||
// any other function that calls that function. However, it's standard practice to
|
||||
// always add the function prototype to a header file (*.h) and then #include that
|
||||
// file at the top. This prevents any issues where a function might be called
|
||||
// before the compiler knows of its existence, while also giving the developer a
|
||||
// clean header file to share with the rest of the project.
|
||||
// any other function that calls that function. However, it's standard practice
|
||||
// to always add the function prototype to a header file (*.h) and then #include
|
||||
// that file at the top. This prevents any issues where a function might be
|
||||
// called before the compiler knows of its existence, while also giving the
|
||||
// developer a clean header file to share with the rest of the project.
|
||||
|
||||
// Your program's entry point is a function called "main". The return type can
|
||||
// be anything, however most operating systems expect a return type of `int` for
|
||||
@ -125,7 +129,8 @@ int main (int argc, char** argv)
|
||||
short x_short = 0;
|
||||
|
||||
// chars are defined as the smallest addressable unit for a processor.
|
||||
// This is usually 1 byte, but for some systems it can be more (ex. for TMS320 from TI it's 2 bytes).
|
||||
// This is usually 1 byte, but for some systems it can be more
|
||||
// (ex. for TMS320 from TI it's 2 bytes).
|
||||
char x_char = 0;
|
||||
char y_char = 'y'; // Char literals are quoted with ''
|
||||
|
||||
@ -153,8 +158,8 @@ int main (int argc, char** argv)
|
||||
// sizeof(obj) yields the size of the expression (variable, literal, etc.).
|
||||
printf("%zu\n", sizeof(int)); // => 4 (on most machines with 4-byte words)
|
||||
|
||||
// If the argument of the `sizeof` operator is an expression, then its argument
|
||||
// is not evaluated (except VLAs (see below)).
|
||||
// If the argument of the `sizeof` operator is an expression, then its
|
||||
// argument is not evaluated (except VLAs (see below)).
|
||||
// The value it yields in this case is a compile-time constant.
|
||||
int a = 1;
|
||||
// size_t is an unsigned integer type of at least 2 bytes used to represent
|
||||
@ -171,15 +176,15 @@ int main (int argc, char** argv)
|
||||
// You can initialize an array of twenty ints that all equal 0 thusly:
|
||||
int my_array[20] = {0};
|
||||
// where the "{0}" part is called an "array initializer".
|
||||
// All elements (if any) past the ones in the initializer are initialized to 0:
|
||||
// Elements (if any) past the ones in the initializer are initialized to 0:
|
||||
int my_array[5] = {1, 2};
|
||||
// So my_array now has five elements, all but the first two of which are 0:
|
||||
// [1, 2, 0, 0, 0]
|
||||
// NOTE that you get away without explicitly declaring the size
|
||||
// of the array IF you initialize the array on the same line:
|
||||
// NOTE that you get away without explicitly declaring the size of the
|
||||
// array IF you initialize the array on the same line:
|
||||
int my_array[] = {0};
|
||||
// NOTE that, when not declaring the size, the size of the array is the number
|
||||
// of elements in the initializer. With "{0}", my_array is now of size one: [0]
|
||||
// NOTE that, when not declaring the size, the array's size is the number of
|
||||
// elements in the initializer. With "{0}", my_array is now of size one: [0]
|
||||
// To evaluate the size of the array at run-time, divide its byte size by the
|
||||
// byte size of its element type:
|
||||
size_t my_array_size = sizeof(my_array) / sizeof(my_array[0]);
|
||||
@ -249,7 +254,7 @@ int main (int argc, char** argv)
|
||||
i2 * i1; // => 2
|
||||
i1 / i2; // => 0 (0.5, but truncated towards 0)
|
||||
|
||||
// You need to cast at least one integer to float to get a floating-point result
|
||||
// You need to cast at least one int to float to get a floating-point result
|
||||
(float)i1 / i2; // => 0.5f
|
||||
i1 / (double)i2; // => 0.5 // Same with double
|
||||
f1 / f2; // => 0.5, plus or minus epsilon
|
||||
@ -366,13 +371,17 @@ int main (int argc, char** argv)
|
||||
printf("\n");
|
||||
|
||||
// *****NOTES*****:
|
||||
// Loops and Functions MUST have a body. If no body is needed:
|
||||
// If the body of control expression is only one statement then parentheses
|
||||
// are optional, but recommended:
|
||||
for (jj = 0; jj < 5; jj++)
|
||||
printf("%d\n", jj);
|
||||
|
||||
// Loops and if statements MUST have a body. If no body is needed:
|
||||
int i;
|
||||
for (i = 0; i <= 5; i++) {
|
||||
; // use semicolon to act as the body (null statement)
|
||||
}
|
||||
// Or
|
||||
for (i = 0; i <= 5; i++);
|
||||
for (i = 0; i <= 5; i++); // semicolon acts as the body (null statement)
|
||||
|
||||
// branching with multiple choices: switch()
|
||||
switch (a) {
|
||||
@ -441,8 +450,9 @@ int main (int argc, char** argv)
|
||||
// without warning.
|
||||
printf("%d\n", (unsigned char) 257); // => 1 (Max char = 255 if char is 8 bits long)
|
||||
|
||||
// For determining the max value of a `char`, a `signed char` and an `unsigned char`,
|
||||
// respectively, use the CHAR_MAX, SCHAR_MAX and UCHAR_MAX macros from <limits.h>
|
||||
// For determining the max value of a `char`, a `signed char` and an
|
||||
// `unsigned char`, respectively, use the CHAR_MAX, SCHAR_MAX and UCHAR_MAX
|
||||
// macros from <limits.h>
|
||||
|
||||
// Integral types can be cast to floating-point types, and vice-versa.
|
||||
printf("%f\n", (double) 100); // %f always formats a double...
|
||||
@ -453,9 +463,9 @@ int main (int argc, char** argv)
|
||||
// Pointers
|
||||
///////////////////////////////////////
|
||||
|
||||
// A pointer is a variable declared to store a memory address. Its declaration will
|
||||
// also tell you the type of data it points to. You can retrieve the memory address
|
||||
// of your variables, then mess with them.
|
||||
// A pointer is a variable declared to store a memory address. Its declaration
|
||||
// will also tell you the type of data it points to. You can retrieve the
|
||||
// memory address of your variables, then mess with them.
|
||||
|
||||
int x = 0;
|
||||
printf("%p\n", (void *)&x); // Use & to retrieve the address of a variable
|
||||
@ -493,9 +503,9 @@ int main (int argc, char** argv)
|
||||
int* x_ptr = x_array;
|
||||
// x_ptr now points to the first element in the array (the integer 20).
|
||||
// This works because arrays often decay into pointers to their first element.
|
||||
// For example, when an array is passed to a function or is assigned to a pointer,
|
||||
// it decays into (implicitly converted to) a pointer.
|
||||
// Exceptions: when the array is the argument of the `&` (address-of) operator:
|
||||
// For example, when an array is passed to a function or is assigned to a
|
||||
// pointer, it decays into (implicitly converted to) a pointer.
|
||||
// Exception: when the array is the argument of the `&` (address-of) operator:
|
||||
int arr[10];
|
||||
int (*ptr_to_arr)[10] = &arr; // &arr is NOT of type `int *`!
|
||||
// It's of type "pointer to array" (of ten `int`s).
|
||||
@ -514,22 +524,23 @@ int main (int argc, char** argv)
|
||||
|
||||
// You can also dynamically allocate contiguous blocks of memory with the
|
||||
// standard library function malloc, which takes one argument of type size_t
|
||||
// representing the number of bytes to allocate (usually from the heap, although this
|
||||
// may not be true on e.g. embedded systems - the C standard says nothing about it).
|
||||
// representing the number of bytes to allocate (usually from the heap,
|
||||
// although this may not be true on e.g. embedded systems - the C standard
|
||||
// says nothing about it).
|
||||
int *my_ptr = malloc(sizeof(*my_ptr) * 20);
|
||||
for (xx = 0; xx < 20; xx++) {
|
||||
*(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx
|
||||
} // Initialize memory to 20, 19, 18, 17... 2, 1 (as ints)
|
||||
|
||||
// Be careful passing user-provided values to malloc! If you want
|
||||
// to be safe, you can use calloc instead (which, unlike malloc, also zeros out the memory)
|
||||
// Be careful passing user-provided values to malloc! If you want to be safe,
|
||||
// you can use calloc instead (which, unlike malloc, also zeros the memory)
|
||||
int* my_other_ptr = calloc(20, sizeof(int));
|
||||
|
||||
// Note that there is no standard way to get the length of a
|
||||
// dynamically allocated array in C. Because of this, if your arrays are
|
||||
// going to be passed around your program a lot, you need another variable
|
||||
// to keep track of the number of elements (size) of an array. See the
|
||||
// functions section for more info.
|
||||
// Note that there is no standard way to get the length of a dynamically
|
||||
// allocated array in C. Because of this, if your arrays are going to be
|
||||
// passed around your program a lot, you need another variable to keep track
|
||||
// of the number of elements (size) of an array. See the functions section
|
||||
// for more info.
|
||||
size_t size = 10;
|
||||
int *my_arr = calloc(size, sizeof(int));
|
||||
// Add an element to the array
|
||||
@ -541,9 +552,9 @@ int main (int argc, char** argv)
|
||||
}
|
||||
my_arr[10] = 5;
|
||||
|
||||
// Dereferencing memory that you haven't allocated gives
|
||||
// "unpredictable results" - the program is said to invoke "undefined behavior"
|
||||
printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? It may even crash.
|
||||
// Dereferencing memory that you haven't allocated gives "unpredictable
|
||||
// results" - the program is said to invoke "undefined behavior"
|
||||
printf("%d\n", *(my_ptr + 21)); // => Prints who-knows-what? It may even crash
|
||||
|
||||
// When you're done with a malloc'd block of memory, you need to free it,
|
||||
// or else no one else can use it until your program terminates
|
||||
@ -552,8 +563,8 @@ int main (int argc, char** argv)
|
||||
|
||||
// Strings are arrays of char, but they are usually represented as a
|
||||
// pointer-to-char (which is a pointer to the first element of the array).
|
||||
// It's good practice to use `const char *' when referring to a string literal,
|
||||
// since string literals shall not be modified (i.e. "foo"[0] = 'a' is ILLEGAL.)
|
||||
// It's good practice to use `const char *' when referring to a string literal
|
||||
// since string literals shall not be modified (i.e. foo[0] = 'a' is ILLEGAL.)
|
||||
const char *my_str = "This is my very own string literal";
|
||||
printf("%c\n", *my_str); // => 'T'
|
||||
|
||||
@ -635,11 +646,11 @@ printf("first: %d\nsecond: %d\n", first, second);
|
||||
// Return multiple values.
|
||||
// C does not allow for returning multiple values with the return statement. If
|
||||
// you would like to return multiple values, then the caller must pass in the
|
||||
// variables where they would like the returned values to go. These variables must
|
||||
// be passed in as pointers such that the function can modify them.
|
||||
int return_multiple( int *array_of_3, int *ret1, int *ret2, int *ret3)
|
||||
// variables where they would like the returned values to go. These variables
|
||||
// must be passed in as pointers such that the function can modify them.
|
||||
int return_multiple(int *array_of_3, int *ret1, int *ret2, int *ret3)
|
||||
{
|
||||
if(array_of_3 == NULL)
|
||||
if (array_of_3 == NULL)
|
||||
return 0; //return error code (false)
|
||||
|
||||
//de-reference the pointer so we modify its value
|
||||
@ -672,15 +683,15 @@ printIntArray(my_arr, size);
|
||||
// will print "arr[0] is: 1" etc
|
||||
*/
|
||||
|
||||
// if referring to external variables outside function, you should use the extern keyword.
|
||||
// if referring to external variables outside function, use the extern keyword.
|
||||
int i = 0;
|
||||
void testFunc() {
|
||||
void testFunc(void) {
|
||||
extern int i; //i here is now using external variable i
|
||||
}
|
||||
|
||||
// make external variables private to source file with static:
|
||||
static int j = 0; //other files using testFunc2() cannot access variable j
|
||||
void testFunc2() {
|
||||
void testFunc2(void) {
|
||||
extern int j;
|
||||
}
|
||||
// The static keyword makes a variable inaccessible to code outside the
|
||||
@ -693,6 +704,18 @@ void testFunc2() {
|
||||
// declared with some other starting value.
|
||||
//**You may also declare functions as static to make them private**
|
||||
|
||||
// Note that before C23, and unlike C++, functions taking no arguments without
|
||||
// an explicit `void` inside the parameter list will be treated as taking an
|
||||
// unknown number of arguments rather than no arguments.
|
||||
void testFunc3(void) {
|
||||
// Functions can be prototyped inside other functions
|
||||
void foobie();
|
||||
void bletch(void);
|
||||
|
||||
foobie(1, 2, 3); // This will give a warning at most, not an error
|
||||
bletch(1, 2, 3); // This will produce an error
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// User-defined types and structs
|
||||
///////////////////////////////////////
|
||||
@ -713,10 +736,16 @@ struct rectangle {
|
||||
// due to potential padding between the structure members (this is for alignment
|
||||
// reasons). [1]
|
||||
|
||||
void function_1()
|
||||
void function_1(void)
|
||||
{
|
||||
struct rectangle my_rec = { 1, 2 }; // Fields can be initialized immediately
|
||||
|
||||
// Fields can also be initialized in an arbitrary order with the field name
|
||||
struct rectangle my_rec2 = {
|
||||
.height = 2,
|
||||
.width = 1
|
||||
};
|
||||
|
||||
// Access struct members with .
|
||||
my_rec.width = 10;
|
||||
my_rec.height = 20;
|
||||
@ -760,10 +789,10 @@ int areaptr(const rect *r)
|
||||
// Function pointers
|
||||
///////////////////////////////////////
|
||||
/*
|
||||
At run time, functions are located at known memory addresses. Function pointers are
|
||||
much like any other pointer (they just store a memory address), but can be used
|
||||
to invoke functions directly, and to pass handlers (or callback functions) around.
|
||||
However, definition syntax may be initially confusing.
|
||||
At run time, functions are located at known memory addresses. Function pointers
|
||||
are much like any other pointer (they just store a memory address), but can be
|
||||
used to invoke functions directly, and to pass handlers (or callback functions)
|
||||
around. However, definition syntax may be initially confusing.
|
||||
|
||||
Example: use str_reverse from a pointer
|
||||
*/
|
||||
@ -773,12 +802,13 @@ void str_reverse_through_pointer(char *str_in) {
|
||||
f = &str_reverse; // Assign the address for the actual function (determined at run time)
|
||||
// f = str_reverse; would work as well - functions decay into pointers, similar to arrays
|
||||
(*f)(str_in); // Just calling the function through the pointer
|
||||
// f(str_in); // That's an alternative but equally valid syntax for calling it.
|
||||
// f(str_in); // That's an alternative but equally valid syntax for calling it
|
||||
}
|
||||
|
||||
/*
|
||||
As long as function signatures match, you can assign any function to the same pointer.
|
||||
Function pointers are usually typedef'd for simplicity and readability, as follows:
|
||||
As long as function signatures match, you can assign any function to the same
|
||||
pointer. Function pointers are usually typedef'd for simplicity and readability,
|
||||
as follows:
|
||||
*/
|
||||
|
||||
typedef void (*my_fnp_type)(char *);
|
||||
@ -864,8 +894,8 @@ as the C file.
|
||||
*/
|
||||
|
||||
/* A safe guard to prevent the header from being defined too many times. This */
|
||||
/* happens in the case of circle dependency, the contents of the header is */
|
||||
/* already defined. */
|
||||
/* happens in the case of circlular dependencies, or such as when a header is */
|
||||
/* included alongside a header that includes the same header itself. */
|
||||
#ifndef EXAMPLE_H /* if EXAMPLE_H is not yet defined. */
|
||||
#define EXAMPLE_H /* Define the macro EXAMPLE_H. */
|
||||
|
||||
@ -895,9 +925,10 @@ typedef struct Node
|
||||
/* So can enumerations. */
|
||||
enum traffic_light_state {GREEN, YELLOW, RED};
|
||||
|
||||
/* Function prototypes can also be defined here for use in multiple files, */
|
||||
/* but it is bad practice to define the function in the header. Definitions */
|
||||
/* should instead be put in a C file. */
|
||||
/* Function prototypes can also be defined here for use in multiple files, */
|
||||
/* but it is bad practice to define the function in the header. Definitions */
|
||||
/* should instead be put in a C file. An uncommon exception is when defining */
|
||||
/* static inline functions. */
|
||||
Node createLinkedList(int *vals, int len);
|
||||
|
||||
/* Beyond the above elements, other definitions should be left to a C source */
|
||||
|
@ -30,7 +30,8 @@ program example ! declare a program called example.
|
||||
|
||||
! All declarations must come before statements and expressions.
|
||||
|
||||
implicit none ! prevents dynamic declaration of variables (recommended!)
|
||||
implicit none ! prevents dynamic declaration of variables
|
||||
! Recommended!
|
||||
! Implicit none must be redeclared in every function/program/module...
|
||||
|
||||
! IMPORTANT - Fortran is case insensitive.
|
||||
@ -45,10 +46,14 @@ program example ! declare a program called example.
|
||||
complex :: w = (0, 1) ! sqrt(-1)
|
||||
character(len=3) :: month ! string of 3 characters.
|
||||
|
||||
real :: array(6) ! declare an array of 6 reals.
|
||||
real, dimension(4) :: arrayb ! another way to declare an array.
|
||||
integer :: arrayc(-10:10) ! an array with a custom index.
|
||||
real :: array2d(3, 2) ! multidimensional array.
|
||||
! declare an array of 6 reals.
|
||||
real :: array(6)
|
||||
! another way to declare an array.
|
||||
real, dimension(4) :: arrayb
|
||||
! an array with a custom index -10 to 10 (inclusive)
|
||||
integer :: arrayc(-10:10)
|
||||
! A multidimensional array.
|
||||
real :: array2d(3, 2)
|
||||
|
||||
! The '::' separators are not always necessary but are recommended.
|
||||
|
||||
@ -77,7 +82,7 @@ program example ! declare a program called example.
|
||||
! Assignment & Arithmetic
|
||||
! =======================
|
||||
|
||||
Z = 1 ! assign to variable z declared above (case insensitive).
|
||||
Z = 1 ! assign to variable z declared above
|
||||
j = 10 + 2 - 3
|
||||
a = 11.54/(2.3*3.1)
|
||||
b = 2**3 ! exponentiation
|
||||
@ -86,7 +91,7 @@ program example ! declare a program called example.
|
||||
! ===================================
|
||||
|
||||
! Single-line if statement
|
||||
if (z == a) b = 4 ! condition always need surrounding parentheses.
|
||||
if (z == a) b = 4 ! conditions always need parentheses.
|
||||
|
||||
if (z /= a) then ! z not equal to a
|
||||
! Other symbolic comparisons are < > <= >= == /=
|
||||
@ -98,13 +103,13 @@ program example ! declare a program called example.
|
||||
b = 5 ! execution block must be on a new line.
|
||||
else
|
||||
b = 10
|
||||
end if ! end statement needs the 'if' (or can use 'endif').
|
||||
end if ! end statement needs the 'if'
|
||||
|
||||
if (.NOT. (x < c .AND. v >= a .OR. z == z)) then ! boolean operators.
|
||||
inner: if (.TRUE.) then ! can name if-construct.
|
||||
b = 1
|
||||
end if inner ! then must name endif statement.
|
||||
end if
|
||||
endif ! 'endif' is equivalent to 'end if'
|
||||
|
||||
i = 20
|
||||
select case (i)
|
||||
@ -128,16 +133,16 @@ program example ! declare a program called example.
|
||||
j = -1
|
||||
end select monthly
|
||||
|
||||
do i = 2, 10, 2 ! loops from 2 to 10 (inclusive) in increments of 2.
|
||||
do i = 2, 10, 2 ! loops from 2 to 10 (inclusive) in steps of 2.
|
||||
innerloop: do j = 1, 3 ! loops can be named too.
|
||||
exit ! quits the loop.
|
||||
end do innerloop
|
||||
cycle ! jump to next loop iteration.
|
||||
end do
|
||||
|
||||
! Goto statement exists but it is heavily discouraged though.
|
||||
! Goto statement exists but it is heavily discouraged.
|
||||
goto 10
|
||||
stop 1 ! stops code immediately (returning specified condition code).
|
||||
stop 1 ! stops the program, returns condition code 1.
|
||||
10 j = 201 ! this line is labeled as line 10
|
||||
|
||||
! Arrays
|
||||
@ -209,8 +214,12 @@ program example ! declare a program called example.
|
||||
|
||||
! we can have multiple format specifications.
|
||||
print "(I5,F6.2,E6.2)", 120, 43.41, 43.41
|
||||
print "(3I5)", 10, 20, 30 ! 3 repeats of integers (field width = 5).
|
||||
print "(2(I5,F6.2))", 120, 43.42, 340, 65.3 ! repeated grouping of formats.
|
||||
|
||||
! 3 repeats of integers (field width = 5).
|
||||
print "(3I5)", 10, 20, 30
|
||||
|
||||
! repeated grouping of formats.
|
||||
print "(2(I5,F6.2))", 120, 43.42, 340, 65.3
|
||||
|
||||
! We can also read input from the terminal.
|
||||
read (*, *) v
|
||||
@ -225,8 +234,9 @@ program example ! declare a program called example.
|
||||
|
||||
! To read a file.
|
||||
open (newunit=m, file="records.txt", status="old")
|
||||
! The file is referred to by a 'new unit number', an integer that the compiler
|
||||
! picks for you.
|
||||
! The file is referred to by a 'new unit number',
|
||||
! an integer that the compiler picks for you.
|
||||
|
||||
read (unit=m, fmt="(3F10.2)") a, b, c
|
||||
close (m)
|
||||
|
||||
@ -241,7 +251,7 @@ program example ! declare a program called example.
|
||||
call cpu_time(v) ! sets 'v' to a time in seconds.
|
||||
k = ior(i, j) ! bitwise OR of 2 integers.
|
||||
v = log10(x) ! log base 10.
|
||||
i = floor(b) ! returns the closest integer less than or equal to x.
|
||||
i = floor(b) ! converts b to integer by rounding down.
|
||||
v = aimag(w) ! imaginary part of a complex number.
|
||||
|
||||
! Functions & Subroutines
|
||||
@ -252,7 +262,7 @@ program example ! declare a program called example.
|
||||
|
||||
call routine(a, c, v) ! subroutine call.
|
||||
|
||||
! A function takes a list of input parameters and returns a single value.
|
||||
! A function takes several input parameters and returns a single value.
|
||||
! However the input parameters may still be modified and side effects
|
||||
! executed.
|
||||
|
||||
@ -261,21 +271,22 @@ program example ! declare a program called example.
|
||||
! Function calls can also be evoked within expressions.
|
||||
print *, func2(3, 2, k)
|
||||
|
||||
! A pure function is a function that doesn't modify its input parameters
|
||||
! or cause any side-effects.
|
||||
! A pure function is a function that doesn't modify its input
|
||||
! parameters or cause any side-effects.
|
||||
m = func3(3, 2, k)
|
||||
|
||||
contains ! Zone for defining sub-programs internal to the program.
|
||||
contains ! Start defining the program's internal procedures:
|
||||
|
||||
! Fortran has a couple of slightly different ways to define functions.
|
||||
|
||||
integer function func(a, b, c) ! a function returning an integer value.
|
||||
! implicit none ! subvariable fields can no longer declare implicit none
|
||||
integer, intent(in) :: a, b, c ! type of input parameters defined inside the function.
|
||||
! implicit none ! - no longer used in subvariable fields
|
||||
integer, intent(in) :: a, b, c ! type of input parameters
|
||||
! the return variable defaults to the function name.
|
||||
|
||||
if (a >= 2) then
|
||||
func = a + b + c ! the return variable defaults to the function name.
|
||||
return ! can return the current value from the function at any time.
|
||||
func = a + b + c
|
||||
return ! returns the current value at 'func'
|
||||
end if
|
||||
func = a + c
|
||||
|
||||
@ -286,17 +297,20 @@ contains ! Zone for defining sub-programs internal to the pro
|
||||
integer, intent(in) :: a, b ! can declare and enforce that variables
|
||||
!are not modified by the function.
|
||||
integer, intent(inout) :: c
|
||||
integer :: f ! function return type declared inside the function.
|
||||
integer :: cnt = 0 ! GOTCHA - initialisation implies variable is
|
||||
!saved between function calls.
|
||||
integer :: f
|
||||
! function return type declared inside the function.
|
||||
integer :: cnt = 0 ! GOTCHA -
|
||||
! assigning a value at initalization
|
||||
! implies that the variable is
|
||||
! saved between function calls.
|
||||
|
||||
f = a + b - c
|
||||
c = 4 ! altering the value of an input variable.
|
||||
c = 4 ! changing value of input variable c.
|
||||
cnt = cnt + 1 ! count number of function calls.
|
||||
|
||||
end function func2
|
||||
|
||||
pure function func3(a, b, c) ! a pure function can have no side-effects.
|
||||
pure function func3(a, b, c) ! a pure function has no side-effects.
|
||||
integer, intent(in) :: a, b, c
|
||||
integer :: func3
|
||||
|
||||
@ -304,6 +318,8 @@ contains ! Zone for defining sub-programs internal to the pro
|
||||
|
||||
end function func3
|
||||
|
||||
! a subroutine does not return anything,
|
||||
! but can change the value of arguments.
|
||||
subroutine routine(d, e, f)
|
||||
real, intent(inout) :: f
|
||||
real, intent(in) :: d, e
|
||||
@ -312,7 +328,8 @@ contains ! Zone for defining sub-programs internal to the pro
|
||||
|
||||
end subroutine routine
|
||||
|
||||
end program example ! End of Program Definition -----------------------
|
||||
end program example
|
||||
! End of Program Definition -----------------------
|
||||
|
||||
! Functions and Subroutines declared externally to the program listing need
|
||||
! to be declared to the program using an Interface declaration (even if they
|
||||
@ -350,7 +367,8 @@ module fruity
|
||||
use fruit, only: apple, pear ! use apple and pear from fruit module.
|
||||
implicit none ! comes after module imports.
|
||||
|
||||
private ! make things private to the module (default is public).
|
||||
! By default all module data and functions will be public
|
||||
private ! Instead set default to private
|
||||
! Declare some variables/functions explicitly public.
|
||||
public :: apple, mycar, create_mycar
|
||||
! Declare some variables/functions private to the module (redundant here).
|
||||
|
Loading…
Reference in New Issue
Block a user