GNU Pascal Coding Standards
Copyright (C) 2001-2003 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.
Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided that
the entire resulting derived work is distributed under the terms of
a permission notice identical to this one.
Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for
modified versions, except that this permission notice may be stated
in a translation approved by the copyright holders.
Version
Last updated 2003-04-24.
About the GNU Pascal Coding Standards
The GNU Pascal Coding Standards were designed by a group of GNU
Pascal project volunteers. The aim of this document is extending the
GNU Coding Standards with specific information relating Pascal
programming. As a matter of fact, the information contained in the
GNU Coding Standards mainly pertains to programs written in the C
language. On the other hand, they also explain many of the rules and
principles that are useful for writing portable, robust and reliable
programs. Most of those general topics could be shared with this
document with just a few specific notes, thus cross references are
provided which will lead you to the more extensive information
contained in the GNU Coding Standards.
This release of the GNU Pascal Coding Standards was last updated
2003-04-24.
The GNU Pascal Coding Standards are available as part of the GPC
distribution – in binary distributions as info files, in source
distributions also as Texinfo files from which further formats such
as HTML, PostScript and PDF can be generated. An HTML version is
also available on GPC's home page, http://www.gnu-pascal.de.
Corrections or suggestions for this document should be sent to the GNU
Pascal Compiler Documentation mailing list, gpc-doc@gnu.de. If
you make a suggestion, please include a suggested new wording for it;
our time is limited. A context diff to the “source” Texinfo file
would be very appreciated, if at all possible. If you can't provide the
context diff, please feel free to mail your suggestion anyway.
These people are the tyrants who are imposing their coding style to the
community so far: Peter Gerwinski peter(at)gerwinski.de , Frank
Heckenbach frank(at)pascal.gnu.de , Markus Gerwinski
markus(at)gerwinski.de , Dominik Freche
dominik.freche(at)gmx.net , Nicola Girardi
nicola(at)g-n-u.de .
Keeping Free Software Free
This chapter from the GNU Coding Standards discusses how you can make
sure that GNU software avoids legal difficulties, and other related
issues. See Intellectual Property.
General Program Design
This chapter discusses some of the issues you should take into account
when designing your program.
Which Language to Use
We support the idea that a variety of programming languages is a good
thing and that different languages are appropriate for different kinds
of tasks. Unlike the GNU Coding Standards (see Source Language), we do not try to persuade you to use C, Pascal or any
single language for everything.
If you're reading this, you have probably already decided to use Pascal
for some project or are considering using it. This documentation will
suggest you how to format your Pascal code when you do so.
Linking to C libraries
You can link a C library or C object code to your Pascal program or
unit. Please note the description in the GPC manual on how to do so
(see Other Languages).
In particular, to access C libraries, we strongly recommend using C
wrappers. This is a portability issue. There might be changes in
different versions of the library which might affect direct
external declarations in Pascal code. You should update the
wrappers so that Pascal programs or units work with whatever version
of the library you have.
There are times when you deal with large packages and you can't easily
retain compatibility to different versions of the packages themselves.
In this case, you can link directly to the library you're going to work
with, and link a supplementary C file which does nothing but the version
check. This is an example:
#include <foo.h>
#if FOO_MAJOR != 1 || FOO_MINOR != 2
#error The GPC interface for libfoo was only written for libfoo-1.2.
#error Please get libfoo-1.2 or check for a version of the GPC interface
#error matching your version of libfoo.
#endif
Note the use of != instead of < or > , to
perform a very strict version check. Please keep in mind that this
is alright if there is only one implementation of a library, i.e.,
you can do this with GTK, but you can't with libc, libm, curses etc.
An automatic header translator is planned which would make the C
wrappers superfluous. This is a highly non-trivial job and it's not
sure that it's at all possible, so it will at least take some time to be
available.
You can assume the GNU C Compiler is used to compile the wrappers and,
in general, any C code snippet you link to your Pascal code. The reason
for such an assumption is that only GNU C Compiler is guaranteed to have
all conventions compatible to GNU Pascal Compiler on every platform they
run on, as they share the same backend. Also, The GNU Pascal Compiler
is always built together with the GNU C Compiler, so gcc can be
assumed to be available wherever gpc is.
Using Non-standard Features
Many GNU Pascal facilities are provided which extend the standard Pascal
language. Whether to use these extensions in implementing your program
is a tedious question.
On the one hand, using the extensions can make a cleaner program. On
the other hand, people will not be able to build the program unless the
GNU Pascal Compiler is available. This might cause the program
not to compile with other compilers.
In general, it is best to retain compatibility to other compilers or to
the language standards, if this compatibility is easy to achieve.
In general, sadly enough, to achieve compatibility you get considerable
drawbacks. For example, you might have to add lots of
{$ifdef} s to cater for some non-standard compilers, which make
the code harder to read, write, test and maintain. Moreover,
{$ifdef} s themselves are non-standard extensions, so you don't
win much this way.
In the end, we suggest not to bother too much about compatibility. All
of the GNU Pascal Compiler interfaces (compiler and Run Time System) are
open. This means they can be implemented for other compilers when
needed or even the same sources can be used provided the license is
preserved (read more about the GNU General Public License at
http://www.gnu.org/copyleft/gpl.html), rather than crippling the
code by not using the extended features. A (limited) example of this
strategy is in the gpc-bp unit for Borland Pascal, distributed
with the GNU Pascal Compiler. You might want to look at its interface
to see what exactly it contains. It's easy to extend it by more
compatibility features when needed, though there are features that
cannot easily be emulated (in particular those that have a special
syntax).
Please do not use the following features, especially the ones that were
implemented just for backward compatibility:
- the
(* *) comments for old terminals where the { and
} characters were not available
- the
# directives and the // comments, as in C/Delphi. If a
file must also be used in C, it may use # directives, the C syntax
in conditionals, and // comments. Examples (as of this
writing, might change in the future) are p/rts/constants.h in the
GNU Pascal Compiler sources, and the tail of crt.inc which is
copied into crtc.h automatically.
- the misuse of typed constants as variables, which is a misfeature of
Borland Pascal.
^A character constants. Use #1 or Chr (1) ,
instead.
CString s (except for C interfaces, of course)
- complicated Borland Pascal code like the following instead of using
WriteStr :
Str (Foo, s);
s := 'Hello ' + s;
- most cases of
FillChar and Move , except for low-level code
and when applied to the characters within a string. Using:
FillChar (s, SizeOf (s), 0);
to clear a string, is wrong in GNU Pascal and inefficient even in
Borland Pascal, since the following could be used:
s := '';
This would only clear the length field of the string s .
- most cases of
GetMem and FreeMem – usually they are a
work-around for missing schemata in other compilers.
- many cases of untyped parameters
- most hand-made file name related routines. (When written in Borland
Pascal, they're usually only applicable to DOS, while the routines in
the
GPC unit provide portable alternatives for most stuff.)
- assembler code, except in very small areas for special optimization,
surrounded by a specific
{$ifdef} (for example, for the
processor type). But then, provide an equivalent plain Pascal version
in the {$else} part – and test it!
- anything that requires the
System unit
- assumption of type-sizes
- assumption of endianness (some systems have higher and lower valued
bytes in a different order than other systems; please see the
glossary See Glossary, for an explanation)
- identifiers starting or ending with underscores or having several
adjacent underscores
- units only written for Borland Pascal compatibility. (see GPC Units) Note,
CRT and Printer are not only for
Borland Pascal compatibility, but also for general use.
The GNU Coding Standards have nice statements on this topic. See Using Extensions.
Program Behavior for All Programs
This chapter from the GNU Coding Standards describes conventions for
writing robust software. It also describes general standards for error
messages, the command line interface, and how libraries should behave.
We encourage you to read that part of the GNU Coding Standards.
See Program Behavior.
Here are special notes for Pascal programming, anyway.
The choice between signal functions, discussed in the GNU Coding
Standards, is done in the Run Time System so you needn't care about it.
Another discrepancy with the GNU Coding Standards is the default
behavior for error checks that detect “impossible” conditions. We
don't suggest just aborting. This implies that every user can be a
programmer, but we don't believe this is realistic. Our advice is to
print a reasonable error message so that users can report bug
descriptions to programmers who didn't notice the bug themselves or
could not reproduce it.
Also, the GNU Coding Standards suggest checking every system call for an
error return. That applies to C. In Pascal, error checking is often
automatic, thus you needn't bother with error checking. Many I/O
routines don't return a value (for example, Reset ), but those
that do should usually be checked.
Of course you can disable automatic error checks and see to them for
yourself. In fact, some errors might cause the program to
automatically abort with an error message. Instead, especially in
units or modules, you might want to report errors and give the user
a chance to intervene and fix things up. To do so, you must use the
{$I-} compiler directive, and check the value of
IOResult (see IOResult) or the global error
variables such as InOutRes (see InOutRes). Note
that I/O routines return immediately if InOutRes is set, so
it's not necessary to check it after each operation, so the
following is possible:
{$local I-}
Rewrite (f, 'bla');
WriteLn (f, 'foo');
WriteLn (f, 'bar');
WriteLn (f, 'baz');
Close (f);
{$endlocal}
if InOutRes <> 0 then
begin
WriteLn (StdErr, GetIOErrorMessage);
...
end;
However in your code you might want to also check Rewrite and
other opening calls, which are the most likely to fail, and you will
avoid unnecessary further calls.
There is a set of routines in the GPC unit for naming temporary files,
configuration files and many other file name related stuff. The
advantages of using these are that they work for different kinds of
systems (for example Unix and DOS), and that future problems can be
corrected in one place in the Run Time System rather than in several
different programs or units.
As far as libraries are concerned, we suggest that you don't put each
routine in a separate file. Hopefully someday the GNU Pascal Compiler
will do this automatically on the linker level. At the moment, we
believe that the convenience to the programmer is much more important
than binary size. We also recommend not using a name prefix, as name
conflicts will be resolved by qualified identifiers
(UnitName.RoutineName ) in the future.
Until then, please use temporary work-arounds when conflicts arise.
Making The Best Use of Pascal
This chapter provides advice on how best to use the Pascal language when
writing software. Of course, the rules apply to published code
only – if you for example want to comment things out with old style
comments like (* this one *) , you should do it temporarily and
remove it before distributing your code. But since you never know if
and when you are going to publish your code, it's a good idea to stick
to the rules from the beginning.
Assorted Pascal Programming Tips
Pascal code file names should have the .pas suffix. The file
name without the suffix should usually correspond to the name of the
program/unit/module, but all in lower case. There should be only one
program/unit/module in a file. (The GNU Pascal Compiler allows several,
but this feature may be dropped in the future.)
Code must compile with the -Wall flag, with and without the
-O2 flag with no warnings. (See Compiler Directives, for
how to intentionally disable certain warnings if really necessary.)
Don't use the automatic Result variable in functions. If you
want one, just declare it:
function Foo (...) = Bar: Integer;
Use the declaration with = , not without it, unless you want to be
strictly PXSC compatible.
If a function returns a Boolean to indicate success, True
should mean success and False failure, unlike some C routines
where 0 means success.
Avoid goto and similar statements, like Exit ,
Return , Break , Continue . Avoid goto at any
price (except possibly a non-local goto to return from
deeply nested, recursive functions in case of error). Avoid the
others if this is possible with reasonable effort. If it would require
an additional Boolean variable, this counts as an excuse for
using those statements if you really want. Note that often, code
becomes significantly simpler by not using Break etc. and
instead using a better loop condition or a different kind of loop.
Never modify for loop counters, or rely on their value after the
loop. (Well, that's not merely a coding style, that's the definition of
Pascal. Doing such things will produce undefined results.)
Never rely on undefined behavior. For example, that global variables
seem to be initialized to 0 at the start of the program, or
perhaps sometimes newly allocated memory seems to be initialized, or
memory after deallocation still seems to hold some values, or that
for loop counters seem to have a certain value after the
loop – none of these is guaranteed, and the behaviour may change
when you change compiler or its version, or when you change
platform. Undefined means undefined, and the fact that such things
might seem to work on all systems you have checked and with 42 other
compilers means exactly nothing.
In comparisons put the “more variable” expression on the left side:
for i := 1 to 10 do
if a[i] = Foo then
for j := 1 to 10 do
if b[j] = a[i] then ...
Considering the second line of the above example, the expression on
the left (a[i] ) varies each turn, but the right side
(Foo ) does not. (In this case we assume that Foo is a
constant or a function which doesn't depend on i or some
other global data. Otherwise it might make sense to put Foo
on the left, and perhaps use an extra comment to point this out.)
The last line of the above example might look strange, because
b[j] and a[i] might look as though they have the same
level of “variableness”. But in fact, j ranges more often
than i , i.e. each time i changes, j has already
changed 10 times.
Avoid code duplication. It is easy to copy the code, but it becomes a
maintenance nightmare to change several similar places. Use routines or
subroutines, units or modules, whatever. Plan each part of the code
so that it can be extended. Don't pull too clever tricks in places
that will likely be changed later.
Do not surround single statements with begin and end ,
unless you have to avoid the dangling else problem or the single line
statement forms a whole routine body! See the following examples:
if foo then
begin
if bar then
baz
end { Avoid the dangling else problem. }
else
qux { Single line statement. }
Do not write empty unit initializers. This is what not to do:
...
procedure Foo;
begin
...
end;
begin
end.
Instead, simply:
...
procedure Foo;
begin
...
end;
end.
Do not write unused declarations, unless in interfaces which are meant
to be used by the importer.
Remember that Boolean s are Boolean s. Please use if
Foo then instead of if Foo = True then , and if not Foo
then instead of if Foo = False then . Also, use until
False in place of until 1 = 0 – this looks smarter. Another
common situation is Foo := Expression instead of if
Expression then Foo := True else Foo := False .
Avoid duplicate global identifiers, i.e. don't overload a built-in
identifier, although the GNU Pascal Compiler allows this, and don't
use the same global identifier in several units or modules. (This
feature will be present in the GNU Pascal Compiler in the future
and be called “qualified identifiers” but still don't use it.)
We discourage the use of global variables for non-global purposes
(e.g., the use of a variable Counter used as a counter in
various local routines). Declare a counter variable for each routine
that needs it, instead. In general, this also allows for better
optimization of the code generated.
When you need an infinite loop (which may be left with
Break ), we suggest you use a repeat rather than a
while loop because it shifts your code less to the right (at
least, if there's more than one statement in the loop). That is:
repeat
...
until False
Instead of:
while True do
begin
...
end
Explicitly Checking Internal Consistency
As stated in the GNU C library documentation (see Consistency Checking), when you're writing a program, it's often a
good idea to put in checks for violations of basic assumptions.
Consider the following procedure in Pascal:
procedure DoSomethingOnAPString (StrPtr: PString);
You may implicitly assume that the above procedure will never be
called with nil as its argument, but it is safer to check for
the “impossible condition”, i.e. check that StrPtr is other
than nil , like this:
procedure DoSomethingOnAPString (StrPtr: PString);
begin
Assert (StrPtr <> nil);
...
end;
When this check fails, the program produces a runtime error. You
then may infer that the code which calls this procedure is buggy (or
that you need to extend this particular routine), so this may indeed
be helpful in locating the problem. In other words, checking for
basic assumptions at the beginning of a routine body or other
strategic places is the right way to make sure a function isn't
being misused.
The GNU C library provides the assert macro for this kind of
checks. GNU Pascal provides a Pascal counterpart which is called
Assert , which behaves a little differently. Assert
won't abort your program, but rather cause a runtime error
(see Assert) which, e.g., you can catch using the
Trap unit (see Trap).
Once you think your program is debugged, you can disable the error
checks performed by the Assert routine by recompiling with
the --no-assertions switch. No change to the source code is
needed in order to disable these checks. Side-effects in the
argument to Assert are still evaluated (unlike in C), so it
is alright to write:
Assert (MyFunction (Foo, Bar) > 0)
This will always call MyFunction , but only make sure that its
result is positive if --no-assertions is not given.
However, it is recommended that you don't disable the consistency
checks unless you can't bear the program to run a little slower.
Formatting Your Source Code
First of all, avoid unnecessary spaces at the end of the lines. Also
remember not to save the file with TAB characters, as different editors
or different configurations will interpret them with a different
amount of spaces, thus breaking indentations. (If you use GNU Emacs,
the untabify function comes in handy; if you use VIM, the
option expandtab (:set et ); in PENG, the option
Expand tabs can be used.)
Please avoid the use of any control characters, except newline, of
course. This means no form feed characters (#12 ), i.e. new page
characters. They are recommended in the GNU Coding Standards to
separate logical parts of a file, but don't use them at least in Pascal
code. No SUB character (#26 ) either, misused as an
end-of-file indicator by DOS. Older DOS editors put that character at
the end of each file for no good reason, though even the FAT file system
knows about the end of a file by its own.
We recommend a maximum line length of 68 characters, so that it can be
printed in TeX with default font on A4, or 78 characters, for
80-column wide screens. This is not a fixed rule because breaking lines
too often decreases readability of source code.
Use empty lines between blocks. Blocks are long comments, type ,
const , var , label sections, routine bodies,
unit/module initializers/finalizers, program , unit ,
interface , implementation , module , export ,
uses , import lines, global compiler directives. As far as
long comments that refer to the following declaration, put only an empty
line before the comment, not between the comment and the declaration
itself. A special exception is between blocks within the same
routine – do not use empty lines there. For example:
procedure Short;
var
Foo: Integer;
Bar: Char;
begin
...
end;
But remember to use empty lines to separate subroutines, like the
following:
procedure Long;
const
...
var
variables used by Sub ...
procedure Sub;
var
...
begin
...
end;
var
variables not used by Sub ...
begin
...
end;
Note that you shouldn't put an empty line after the main routine
declaration, unless a subroutine declaration immediately follows.
Otherwise the main routine declaration would look like a forward
declaration.
Notice that in the code snippet above we separated local variables (or
constants) before and after the subroutine – this is not mandatory.
Of course, what we said for subroutines is also valid for
sub-subroutines at any depth.
An empty line should be put between declarations of the same type, where
appropriate, to separate them logically. In case there is a comment
before the declaration, the empty line must be before the comment.
Otherwise, the empty line goes before the declaration.
Empty lines can be used in long comments to separate paragraphs.
No empty lines at the beginning or ending of a file, only one
newline at the ending. No multiple empty lines.
Commenting Your Work
The comments should be placed in braces like this:
{ This is a nice comment. }
Do not use the old style comment between brackets and asterisks, like
this:
(* This is an ugly comment. One you mustn't write. *)
Also, do not use comments introduced by the double slash:
// Another kind of comment not to write.
Although ISO Pascal explicitly allows for mixed comments, the GNU Pascal
Compiler doesn't even accept it unless you turn it on the option with
the appropriate compiler directive {$mixed-comments} – but you
don't want to do it. Here are a couple of examples of mixed comments,
which you should not follow:
(* This ... }
{ ... and that. *)
Also, try to avoid nested comments, like { { This one } } .
These are alright if you want to put some TeX in a comment or
something more exotic. Whatever reason you have to use nested comments,
you need to turn on the option with the appropriate compiler switch,
which is {$nested-comments} . Do not use the
--nested-comments command line option. Put all such options in
the source, so that someone else trying to compile it doesn't have to
figure out what command line switches are needed, and because command
line options would affect all source files, e.g. when compiling
a project with multiple units/modules.
Please write the comments in your program in English, because English is
the one language that nearly all programmers in all countries can read.
If you do not write English well, please write comments in English as
well as you can, then ask other people to help rewrite them. If you
can't write comments in English, please find someone to work with you
and translate your comments into English.
You should adopt “French Spacing”, i.e. only one space at the end
of a sentence. This way, you can't use GNU Emacs M-a and
M-e key combination to move through sentences. We hope that
you can live without that. Also, please put just one space after the
comment opening brace and before the closing brace.
If a comment regards only one line of code, possibly write it after the
line of code, in the same line, separated from the code with two spaces.
This is also allowed for the interface section of a unit and for global
variables. Most often you are likely to write this sort of comment
beside record/object fields. In other cases, comments go in one or more
lines of their own, like this:
{ foo bar baz }
Or longer:
{ foo bar
baz }
Or with paragraphs:
{ foo bar
baz
qux }
The comments need to be placed before the code they describe, and they
need to get the same indentation level. This example should make this
clear:
{ My types. }
type
...
type
{ My first types. }
Foo = Integer;
...
begin
{ My first statement. }
Bla;
{ Start of loop. }
repeat
{ Body of loop. }
...
{ Finish when Something happens. }
until Something
end;
Note the position for the comment to until .
Comments describing a global declaration should be on one or more
lines of their own, immediately before the declaration. For example:
{ This is Foo. It does this and that. }
procedure Foo;
Do not write “trivial” comments, like the ones listed in the examples
above. You should avoid comments by writing clear code. Linus Torvalds
points this out strongly in the Kernel Coding Style:
Comments are good, but there is also a danger of over-commenting.
Never try to explain how your code works in a comment:
it's much better to write the code so that the working is
obvious, and it's a waste of time to explain badly written code.
Generally, you want your comments to tell what your code does,
not how.
(Note that we otherwise deviate quite a bit from Linus's coding style.)
“Tricky” code is worth being commented. We define “tricky” the code
that does non-obvious things, relies on non-obvious assumptions, has
non-obvious implications, there is anything to note when changing it, is
not what it looks at first sight, there is a side effect, or requires
other parts of the source file to be changed simultaneously with it.
Tricky code should be used very sparingly.
In the case that a comment refers to some other place in the
code, either in the same file or in a different file, please refer to it
not by line number (this will change too often) but by routine name
or context. Also, think whether it is useful to put a comment in the
other place pointing back. (Not always, but sometimes this has
proved useful to us.)
To comment out parts of code that should not be compiled, you need to
surround it with {$if False} ... {$endif} rather than
using a comment.
To separate logical parts within big modules or units, you can use a
special comment – we suggest this fixed pattern as it's easily
searchable:
{@section Name of the section}
{@subsection Name of the subsection}
Note that no space follows the opening brace nor predeces the closing
brace in this case.
A module or unit or library should have a comment for each of its
interface declarations, so that the interface part of the source file is
a reliable source of documentation. This is optional for any
declarations introduced only in the implementation section or in
program s. Of course, several related declarations (e.g.,
groups of constants) can share a comment.
A utility called pas2texi will be written to build Texinfo
files from Pascal comments. This will allow certain kinds of markup
within comments. They will be described in the documentation of
pas2texi and/or in future versions of this document.
You can use “fixme” comments, to point out things to be fixed in the
code, or in a library (or module, or unit, or compiler used) which
directly affect the code, requiring a work-around. These comments are
prepended by at least two @ – add as many @ as the
urgency of the issue increases.
These comments may contain more or less obscure details about the
problem, especially if the root of the problem is elsewhere. For
example, the comment { @@fjf226 } declares the following code
a work-around to a GNU Pascal Compiler problem which is demonstrated by
the GNU Pascal Compiler test program fjf226.pas . (It is a file
you can find in the GNU Pascal Compiler source package.)
“Fixme” comments should not be mixed with ordinary comments. If you
need both kinds, use them separately, even if directly after each
other. They can be used everywhere, even within statements, since they
are temporary in nature. Most normally they happen to fall in the body,
unless they influence interfaces. In particular, interfaces that are
likely to be changed should have a @@ comment immediately
before their description comment.
Order of Code Blocks
Please start each file with a comment containing, in this order:
- a short description telling what the code in the source file does
- a long description going into detail about the code and specifying
sources of information or code
- a copyright notification held by authors of the code
- the license – of course you want to use the GNU General Public License
or Lesser General Public License for your programs and units, don't you?
In general, you should follow this order for declaration blocks:
const declarations
type declarations
var declarations
label declarations
- routines
You may deviate from this order when it is necessary or makes the code
more readable. This is an example where the order can't be respected:
type
TSomething = record
This, That: Integer
end;
const
SomeConst = SizeOf (TSomething);
The rules above apply to declaration blocks within routines, too.
When there are several, more or less independent parts, especially in a
large unit or module, you may apply this order within each part. Do not
put, for example, constants of all parts together. You have to keep the
code readable.
Variables that are used only in the main program must be declared
globally in Pascal, although GNU Pascal offers an extension for
declaring variables at arbitrary places in the code
(see var). In this case, in contrast to the
previous general rule, it is often better to put their declaration just
before the main program's begin , after all routines etc.,
especially when there are more than a few such variables and the size of
the source file is not small. Thus, the variable declaration block is
easier to see and change for the programmer when editing the main
program, and you make sure that routines don't use them accidentally.
When you declare a type together with its pointer type, declare the
pointer first. It is easier to recognize especially if the type is a
long record or object. Also, it makes possible using recursive
structures (i.e., using pointers to a type within this type). You
should prepend a T to the type name and a P to the
associated pointer type. See the example:
type
PMyInt = ^TMyInt;
TMyInt = Integer;
PStrList = ^TStrList;
TStrList = record
Next: PStrList;
s: TString
end;
Note that the Next field is specified first. We suggest always
putting it as the first field in recursive types, as it allows some
generic list routines and may be a little more efficient to walk the
list, i.e. no offsets.
We suggest putting all pointer types within each type declaration
first, although we don't consider this mandatory. This is an example:
type
{ Pointer types }
PFoo = ^TFoo;
PBar = ^TBar;
PBaz = ^TBaz;
{ Some custom integer types }
TFoo = Integer attribute (Size = 16);
TBar = Cardinal attribute (Size = 16);
TBaz = Cardinal attribute (Size = 32);
Within object types you can have three declaration areas. There are
three reserved words for introducing these areas: public ,
protected , private . Within each of these areas follow
this order:
- fields
- constructors
- destructor (there should be only one)
- methods
In the object implementation part, put the routine bodies in the same
order in which they appear in the declaration in the interface. This
also applies to units and modules, in which the implementation should
reflect the interface declarations.
Do not use the trailing ; at the end of a block, i.e. before
end , until , etc. except case – the last branch
before the else branch (or the last branch if there is no
else branch) should have a ; , to avoid problems
like:
case ...
Foo:
if Bar then { later inserted }
begin
...
end { if there's no semicolon here ... }
else { ... this will be mistaken as the then 's else }
...
(Same if the if was there for longer and the else branch
of the case is later inserted.)
In an object, it may look strange to omit the ; after the last
item which is most often a method. Therefore we allow it, and for
consistency also in records.
Capitalization
Reserved words should be all lower case, including directives,
i.e. words that are reserved only in some contexts, like
protected . If you use directives as identifiers (which is likely
to cause you pain) outside of their contexts, write them like
identifiers.
As a special exception, you can use capitalized File when used as
a type of its own, i.e. an untyped file, unlike file of Char .
The same can't be said for procedure as a type (Borland Pascal
style) since File can be a proper type, while
procedure is a type constructor, i.e.:
procedure Foo (var a: File); { This works. }
procedure Foo (var a: procedure); { This doesn't. }
Next issue is capitalization of identifiers. There's no difference
between built-in and user-defined identifiers. Only the first letter
should be capital, or, if there are concatenated words or acronyms, the
first letter of each word should be capital – do not use underscores.
Acronyms that have become part of the natural language can be written
like that. For example, Dos or DOS ; but always
GPC , not Gpc . Here are some examples of identifiers:
Copy , Reset , SubStr , BlockRead ,
IOResult , WriteLn , Sqr , SqRt ,
EOF , EOLn .
These rules apply to constants identifiers, too, unlike C macros.
Also note that very small identifiers can be written lower case,
like i or s1 or xx . Such short identifiers
should be used only locally. They can be used for parameters of
global routines, because the scope of such parameters is local as
well, and their names in fact don't matter at all to the caller. The
use of such identifiers in a global context should be avoided,
especially in units or modules or libraries (because the author
doesn't know in which contexts they will be used).
Please be consistent with your capitalization. You know that Pascal
will not hurt you if you change capitalization for an identifier
throughout the code, but please stick to the same capitalization.
For identifiers for the values of enumeration types and for blocks
of constants, i.e. places where you introduce a lot of identifiers,
it can be useful to use a two-letter lower-case prefix and _ ,
in contrast to the previous rules:
type
TFooBar = (fb_Foo, fb_Bar, fb_Baz, fb_Qux);
{ My Foos }
const
mf_Foo = 1;
mf_Bar = 3;
mf_Baz = 42;
In object oriented code (especially in constructors), there is
often the need to have a parameter correspond to an object field
(e.g., to pass a value with which to initialize the field). Since
both can't be called the same, the field should have the “natural”
name since it's usually used in more routines, and the parameter
name should be “mangled”. FIXME: We haven't found a really
satisfactory rule for mangling yet (some use a as a prefix), and
if you have any good idea, let us know.
As far as macros are concerned, we strongly recommend that you do not
use them. Please, do not use macros in your programs. Try to avoid
using macros in your programs, because they are evil. We believe you
must not use macros in your code. Said that, if you still dare to use a
macro, write it capitalized entirely and separate words with
underscores. Since macros do not follow Pascal's scoping, it makes
sense to write them differently. This applies to conditionals, too.
Use of Compiler Directives
We generally suggest using as few compiler directives as reasonably
possible, because they make the code harder to understand (e.g.,
when checking for side-effects) and to modify (e.g., when moving
parts of code into or out of the scope of compiler directives). The
directives should be invoked like in the example:
{$your-compiler-directive}
Definitely not this way (see Comments):
(*$do-not-use-such-a-compiler-directive*)
Also, definitely not this way, which is dependent on line breaks, unlike
Pascal normally is:
#your-compiler-directive
Same goes for macro definitions:
{$define ...}
This also saves the ending backslash before line breaks, in contrast to
#define . But you will not use macros, will you?
(see Capitalization)
As far as spacing is concerned, don't type a space before the closing
brace, as there can't be one after the opening brace. If you
concatenate many directives together, don't put a space between each of
them, a single comma is enough.
No comments should be inserted within the directives. Write them
separately, instead, like this:
{$X+} { We need extended syntax. }
Borland Pascal allows mixing comments with directives, but it's really a
misuse.
Short forms for calling the directives are alright, but long forms are
at least as good, not to say preferred. Short forms must be written in
caps, while long forms in lower case (except for case-sensitive
arguments like messages and file names – of course, file names must
always be treated as case-sensitive, even on DOS, to preserve code
portability).
You can combine several directives, also mixing short and long ones, in
a single call, for example like the following:
{$gnu-pascal,I-,X+}
Any unit or module should have {$gnu-pascal,I-} or
{$gnu-pascal,I+} near the beginning (after the head comment
with description and license). {$gnu-pascal} lets the unit be
compiled without dialect options even if the main program is compiled
with some. {$I-} or {$I+} indicates to the user (even
though one of them is the default) whether the unit handles/returns
input/output errors or lets them cause runtime errors. The former is
preferable for most units. For programs, this item is optional. Routines
that return input/output errors should have the attribute
iocritical (see attribute):
procedure CriticalRoutine; attribute (iocritical);
{$W-} (no warnings) must only be used locally and must have a
“fixme” comment (see Comments) because it indicates a problem with
the code or the compiler.
Please, don't disable warnings when you're just too lazy to write the
code that does not produce warnings.
Any compiler flags that are not set globally (for example, together with
{$gnu-pascal} , see above) should be set with {$local
...} . In other words, not this way:
{$I-} Reset (f); {$I+}
But this way:
{$local I-} Reset (f); {$endlocal}
The former is wrong if {$I-} was set already. Even if a
programmer might know and take into account which is the global setting,
this might be changed sometime, or part of the code may be copied or
moved. The latter form is safer in these cases.
To make it even clearer, from the last two rules it follows:
{$local W-} Foo; {$endlocal} { @ GPC produces a superfluous warning }
Again, try to avoid local directives. {$I-} is sometimes
needed. {$X+} might be used if really, really
necessary (as locally as possible): avoid pointer arithmetics.
Don't use {$X+} to ignore function results, don't use
{$ignore-function-results} , either. It is too easy to ignore a
result one should not ignore. Sometimes, especially when linking to a
foreign C library, you might have to deal with functions which have a
superfluous result, which you probably don't want to check. You can
declare such functions with the ignorable attribute, so that
their results are silently ignored.
Also use dummy variables if you want to ignore the result of a
particular call to a function whose result should in general not be
ignored. But in such cases check carefully whether the result can
really be ignored safely. If, however, an unexpected result would
indicate an “impossible” situation, it's usually better to check the
result and print a warning or abort in the unexpected case, at least if
DEBUG is defined (see Compiler Directives).
Linker directives, i.e. {$L} for libraries and C (or other
language) source files should be put near the start in programs and
shortly after the implementation line in units or modules.
Several libraries and C source files in one directive are possible
when they belong logically together (for example, a library and its
C wrappers), but not for separate things. This directive should not
be mixed with other directives (which doesn't even work if L
comes first – the other way around it might work, but shouldn't be
used). The external declaration of the library or C routines should
immediately follow the directive (except in a unit or module for
those that go in the interface). Using {$L} in programs is
often not a good idea, making a unit is often better for abstraction
and reuse.
Conditional compilation might be useful sometimes, but you should
use as few {$ifdef} 's as possible, as they decrease
readability. When conditionals are used for differences between
systems, check for features (for example,
__BYTES_LITTLE_ENDIAN__ ) or groups of systems (for example,
__OS_DOS__ ) rather than individual systems, to better cater
for systems you don't know or that may not even exist yet.
If possible (this might not be available), use the predefined
constants (for example, BytesBigEndian , OSDosFlag )
rather than defines – for code that is possible (the “always
false” branch will be optimized away, but you still get its syntax
checked as an additional benefit besides not using the
preprocessor); for type declarations it is usually not possible and
you have to use the defines. A good example is the declaration of
TWindowXY in the CRT unit. See:
TWindowXYInternalCard8 = Cardinal attribute (Size = 8);
TWindowXYInternalFill = Integer attribute (Size = BitSizeOf (Word) - 16);
TWindowXY = packed record
{$ifdef __BYTES_BIG_ENDIAN__}
Fill: TWindowXYInternalFill;
y, x: TWindowXYInternalCard8
{$elif defined (__BYTES_LITTLE_ENDIAN__)}
x, y: TWindowXYInternalCard8;
Fill: TWindowXYInternalFill
{$else}
{$error Endianness is not defined!}
{$endif}
end;
The DEBUG flag should be used for (and only for) code to help
debugging, i.e. code which doesn't change the real functionality.
Programs must compile with and without setting DEBUG . The latter
may run slower and may produce useful additional messages in a suitable
form, i.e. clearly marked as debug messages, for example prefixed with
DEBUG: , and may abort when it detects erroneous or
dubious conditions.
Conditionals can also be used to make different versions of some code,
for example, using GMP numbers if a condition is satisfied and using
normal integers or reals otherwise (GMP is a library for working
with arbitrarily large numbers). In this case, the name and meaning
of all such defines used in a file must be explained in a comment
near the top. (For examples, see the __BP_TYPE_SIZES__ ,
__BP_RANDOM__ and __BP_PARAMSTR_0__ in the System
unit.) The code must compile with any combination of those
conditionals set, which means you have to test exponentially many
cases – here is a good reason to keep their number as small as
possible.
Another similar use of conditionals is to select between different
implementations. You should adopt this strategy only if all of
the implementations are really supported or planned to be supported.
Otherwise, you'd better move the old implementations into your
“museum” and keep the code clean. The notes about code compilation of
the previous rule apply here as well.
When you need to deal with complicated conditionals use Pascal syntax,
i.e. format the conditionals according to the rules for Pascal code,
rather than C syntax. This is a silly example:
{$if defined (Foo) or False}
Instead, this is an example not to follow:
{$if defined (Foo) || 0}
Or even worse:
#if defined (Foo) || 0
A special conditional can be used to comment out code temporarily.
Here's the appropriate syntax:
{$if False} ... {$endif}
A standard conditional statement should be used in programs or units or
modules you distribute to make sure that the appropriate version of the
GNU Pascal Compiler is used. You can follow this template:
{$if __GPC_RELEASE__ < 20020510}
{$error This unit requires GPC release 20020510 or newer.}
{$endif}
How to use spaces in your code
In general, no multiple spaces should be used except for indentation and
as indicated below.
A single space goes before and after operators, and := and
.. as well as : in Write , WriteLn and
WriteStr ; after the comma and other : . This example
ought to make it clearer:
var
Foo: Integer;
...
begin
Foo := 42;
WriteLn (Foo + 3 : 5, ' bar')
end;
No space should go before unary - . In fact, these are the
correct forms: x - 1 , -x , -1 .
A space must go before the opening parenthesis (( ) and after the
closing parenthesis () ), unless adjacent to further parentheses,
brackets, ^ , ; , , . In other words, a space goes
between identifiers or keywords and the opening brace (( ). (All
the other spaces in this example are implied by the previous rule
already.) See:
Foo (Bar^(Baz[Qux * (i + 2)]), Fred (i) + 3);
For indexing arrays actually don't use a space before the opening
bracket, i.e. Foo[42] rather than Foo [42] . However,
insert a space before the opening bracket in array declarations, like:
Foo: array [1 .. 42] of Integer;
A space goes before the opening bracket of a set constructor in
some situations – those brackets should be treated like
parentheses, unlike the brackets used in array indexing. For
example:
x := [0, 2 .. n];
But:
Foo ([1, 2, 3]);
No spaces for . and ^ :
Rec.List^.Next^.Field := Foo
As we already pointed out, a single space goes after the opening brace
and before the closing brace in comments, but not in compiler
directives. Also, and we said this already too somewhere in the manual,
two spaces go before comments after a line of code. For example:
Inc (x); { Increment x. }
Optionally use additional spaces to make “tabular” code. In our
opinion, this increases readability a lot because the human eye and
brain is trained to recognize such structures, and similiarities and
differences between the lines can be easier seen, and when changing the
code, it's easier to find related places. An application of this
principle can be seen in interface declarations (not so much applicable
when separated by comments, but, for example, when described by a shared
comment above them all):
function Pos (const SubString, s: String): Integer;
function LastPos (const SubString, s: String): Integer;
function PosCase (const SubString, s: String): Integer;
function LastPosCase (const SubString, s: String): Integer;
function CharPos (const Chars: CharSet; const s: String): Integer;
function LastCharPos (const Chars: CharSet; const s: String): Integer;
function PosFrom (const SubString, s: String; From: Integer): Integer;
function LastPosTill (const SubString, s: String; Till: Integer): Integer;
function PosFromCase (const SubString, s: String; From: Integer): Integer;
function LastPosTillCase (const SubString, s: String; Till: Integer): Integer;
Also possible:
procedure Foo;
function Bar ...;
procedure Baz;
And, of course:
const
FooBar = 1;
Baz = 2;
Quux = 3;
The same “tabular” strategy used in interfaces and const declarations
can be used in initializers:
const
Foo: TBarArray =
(('Foo' , 3),
('Bar baz', 42),
('' , -1));
And in case statements:
case ReadKeyWord of
kbLeft : if s[n] > l then Dec (s[n]) else s[n] := m[n];
kbRight : if s[n] < m[n] then Inc (s[n]) else s[n] := l;
kbUp : if n > 1 then Dec (n) else n := 5;
kbDown : if n < 5 then Inc (n) else n := 1;
kbHome : s[n] := l;
kbEnd : s[n] := m[n];
kbPgUp,
kbCtrlPgUp: n := 1;
kbPgDn,
kbCtrlPgDn: n := 5;
kbCR : Done := True;
end
And optionally in other code:
WriteCharAt (1, 1, 1, Frame[1], TextAttr);
WriteCharAt (2, 1, w - 2, Frame[2], TextAttr);
WriteCharAt (w, 1, 1, Frame[3], TextAttr);
Where to break your lines of code
A line break is optional after local const , type ,
var declarations if they contain only a single declaration (but
it is possible to have multiple identifiers in a single line).
procedure Baz;
var Foo, Bar: Integer;
begin
...
end;
Of course, this is also accepted:
procedure Baz;
var
Foo, Bar: Integer;
begin
...
end;
But don't follow this example:
procedure Baz;
var Foo, Bar: Integer;
Qux: Real;
begin
...
end;
If you have many declarations you can break lines several ways. The
following is the preferred form for var declarations:
var
Foo, Bar, Baz, Qux, Quux, Corge, Grault, Garply, Waldo, Fred,
Plugh, Xyzzy, Thud: Integer;
or:
var
Foo, Bar, Baz, Qux, Quux, Corge, Grault, Garply, Waldo: Integer;
Fred, Plugh, Xyzzy, Thud: Integer;
This one, instead, is more suitable to record and public
object fields, especially if there's a comment for many or each
of them:
var
Foo,
Bar,
Baz,
Qux: Integer;
No line break after var declarations within statement blocks,
because they allow only one declaration, and doing a line break would
look like further ones were allowed.
Foo := Bar;
var Baz: array [1 .. Foo] of Integer;
As they are a GNU Pascal extension, use these declarations sparingly,
for example for variables whose size depends on values computed within
the routine, or for variables within unit or module initializers or
finalizers to avoid global variables, although you might want to think
about using a subroutine.
Do not insert a line break after label . This is how you should
declare labels:
label Foo, Bar, Baz;
And, for completeness, here's how not to do it:
label
Foo,
Bar,
Baz;
Several declarations in different lines don't even work:
label
Foo;
Bar;
Baz;
Here's an example on how to use line breaks within a case statement.
case
foo:
begin
...
end;
bar,
baz .. qux:
...
else
...
end;
Or (“tabular”):
case
foo: begin
...
end;
bar,
baz .. qux: ...
else ...
end;
Long statements or declarations should be broken either always before
operators or always after them (where the extent of always is at least
one routine) or after a comma, with indentation such as to make the
meaning clear:
if (x = y)
and (foo
or (bar
and (baz or qux))
or fred) then
or:
if (x = y) and
(foo or
(bar and
(baz or qux)) or
fred) then
Here's how to use line breaks within if-then-else statements. Another
use for it is where you would use a case statement if it was
possible, but it isn't possible (for example because the types are not
ordinal, or the values to be compared to are not constant, or the
comparison involves a function (StrEqualCase , or there are
additional conditions).
if ... then
a
else if ... then
b
else
c
If a and non-a are main cases, and b and c
are sub-cases of non-a , use the following (the distinction might
be a matter of taste sometimes):
if ... then
a
else
if ... then
b
else
c
The following (biologically quite incomplete) example contains a
mixture of both forms which we consider reasonable:
if Habitat = 'Water' then
{ Animals living in water }
WriteLn ('Is it a fish?')
else if Habitat = 'Air' then
{ Animals living in air }
WriteLn ('Is it a bird?')
else
{ Animals living on land }
if Legs = 8 then
WriteLn ('Is it a spider?')
else
WriteLn ('Is it a gnu?')
The main cases are determined by the habitat, and the number of legs
determines some sub-cases.
For normal control loops here's a brief list of possibilities:
for ... do
...
while ... do
...
repeat
...
until ...
If there is only one command after the if clause, or in a
for or while loop, or between repeat and
until , and if that command is short enough, you can put the
statement on one line only, like this:
if ... then ...
for ... do ...
while ... do ...
repeat ... until ...
Here's how to behave when begin and end are involved.
if ... then
begin
...
end
for ... do
begin
...
end
while ... do
begin
...
end
The indentation is 2 characters wide, for each begin ,
then , else , case , do (for ,
while , with , to begin , to end ),
repeat , record , object , type ,
const , var , label .
The bodies and local variables etc. of global routines must not be
indented, just like global variables etc. Each subroutine (header
and body) and its declarations, on the contrary, must be indented.
program Prog;
var
GlobalVar: Integer;
procedure GlobalProc;
var LocalVar: Integer;
procedure LocalProc;
var LocalLocalVar: Integer;
begin
WriteLn ('This is a local procedure.')
end;
begin
WriteLn ('This is a global procedure.')
end;
begin
WriteLn ('This is the main program.')
end.
Variant records should be indented as follows:
type
Foo = record
NonVariant: Foo;
case Discriminant: Bar of
Val1: (Variant1: Baz;
Variant2: Qux);
Val2: (Variant3: Fred)
end;
var
Foo: record
[ as above ]
end = [ initializer ]
Bigger indentation, i.e. more than 2 characters wide, can be used to
break statements or declarations or to get a “tabular” code.
Conditionals ({$ifdef} ) should be on the same indentation level
as the code they affect:
begin
{$ifdef DEBUG}
WriteLn ('Debugging version');
{$endif}
...
end;
Short conditionals which affect only an expression can be written within
a single line:
Foo := {$ifdef DEBUG} 'debug' {$else} 'release' {$endif};
If they are intentionally used in a way contrary to normal syntactic
rules, put them where they seem to fit best and write a comment:
begin
{ Do the code unconditionally if debugging }
{$ifndef DEBUG}
if SomeCondition then
{$endif}
begin
...
end
end;
Most times you will find a nicer and not less efficient way of writing
the same statements. In this case, it can be done this way:
begin
if {$ifdef DEBUG} True {$else} SomeCondition {$endif} then
begin
...
end
end;
Or better yet:
{ globally }
const
DebugFlag = {$ifdef DEBUG} True {$else} False {$endif};
begin
if DebugFlag or SomeCondition then
begin
...
end
end;
Strings
Most rules we have covered so far do not apply within strings. In
general, messages contained in strings should follow the GNU Coding
Standards, for example, put quoted names within ` and ' ,
although this means you have to double the ' in a Pascal string.
See Errors, for more information.
Normally you should use strings enclosed in single quotes, like
'this nice string that you are reading' . Use strings in double
quotes when you need C style escape sequences like "\t" . Note
that NewLine ("\n" ) is predefined, so using NewLine
is preferable unless you have to use a C style string for other
purposes.
You can use multiline strings like the following:
WriteLn ('Hello
world')
or (perhaps preferable, especially if the text in the string contains
paragraphs and/or indentation itself):
WriteLn (
'Hello
world')
However, it is also possible to use:
WriteLn ('Hello' + NewLine + 'world')
(Note that the above example won't compile without using the
GPC unit.)
Or, of course:
WriteLn ('Hello');
WriteLn ('world')
When you want to check if a string is empty, use this syntax:
if s = '' then
...
The GNU Pascal Compiler will eventually optimize it to the following
more efficient test, hence you can use the previous, shorter one
with no regret:
if Length (s) = 0 then
...
The same applies for <> , of course, and even for assignments
where s := '' is the recommended form and will be optimized
by GPC to SetLength (s, 0) .
Techniques for internationalization
Please note the description in the GPC manual on how to
do so (see I18N).
MemoryMap
This section of the GNU Coding Standards also applies to GNU Pascal.
Remember that mmap actually means MemoryMap in this
context. See Mmap.
Documenting Programs
We recommend reading the respective section in the GNU Coding Standards,
as it applies to this context, too. See Documentation. There are some notes worth writing here, though.
As far as man pages are concerned, it would be nice to have a man page
referring to the Info documentation. There is a GNU program, called
help2man , which generates a man page based on the --help
output of a program. It works well, except that it always prints
FSF which is not correct for all programs compiled with the GNU
Pascal Compiler, but the output can easily be changed (for example,
automatically using sed ).
However, don't put too much effort in man pages. They might be feasible
initially, but keeping them up to date together with the Texinfo
files means a lot of work. On top of that, if you don't keep them
updated, they are likely to cause more confusion than they help.
On the one hand, if man pages are shortened too much they are likely to
miss important information. On the other hand, if not shortened, they
get hard to navigate.
In other words, devote to Info (i.e., Texinfo) documentation.
The Release Process
Please read the respective chapter in the GNU Coding Standards.
Note that the huge auto-tools effort of C is not needed for normal
GNU Pascal programs. Also Makefiles are often not necessary in GNU
Pascal. See Managing Releases.
Makefile Conventions
For your Pascal project you probably won't need large Makefile s
and you won't need to use autoconf or automake . You can
give the --automake to the GNU Pascal Compiler so that it takes
care of dependencies for you. (As of this writing, the GNU Pascal
Compiler's automake feature has some slight bugs, but they
will be fixed. Also, there is a plan for a utility called gp ,
which is now under development, which will simplify the compilation
process a lot more. Stay tuned. In any case, you usually don't need
to write complex Makefile s yourself.)
A simple Makefile may be in order, like:
GPC_FLAGS=-O2
all: foo
foo: foo.pas unit1.pas
gpc --automake $(GPC_FLAGS) foo.pas
mostlyclean:
-rm -f *.o *.gpi *.gpd core
clean: mostlyclean
-rm -f foo
distclean: clean
extraclean: distclean
-rm -f *~*
maintainer-clean: extraclean
You may, however, want to put other rules into a Makefile to
build documentation, data files, making distributions or whatever.
Such things are outside of the scope of this text. You can usually
do the Pascal compilations with a single gpc --automake call
per program.
Glossary of words used throughout this text
Routines are procedure s, function s,
constructor s, destructor s or (user-defined) operators.
Declarations are those parts of a program that “announce” the
existence and properties of certain objects like constants, types,
variables, routines, units, modules and the program.
Statements are those parts of a program that actually “do”
something. A single statement is an assignment, a procedure call, a
jumping statement (goto , Exit , Return ,
Break , Continue ), an assembler statement, or a
compound statement (begin ... end , if ,
case , repeat , while , for , with )
which in turn may contain one or several statements.
Identifiers are those language elements that give names to objects like
routines, constants, types, variables, units, modules. They can be
(locally) redefined, unlike keywords which are part of fixed syntactic
constructs (for example if ... then ...
else ) and cannot be redefined. Macros are no language elements
at all since they are expanded by the preprocessor and never seen
by the compiler.
Endianness means the order in which the bytes of a value larger than
one byte are stored in memory. This affects, e.g., integer values
and pointers while, e.g., arrays of single-byte characters are not
affected. (see Endianness)
Note: Other items may be inserted here when it appears
useful. If you'd like a definition of some other term, let us know.
Index
|