A Comparison of the Syntax of C/C++ and Pascal
                - ---------- -- --- ------ -- ----- --- ------




                             *** VERSION 1.6 ***


            copyright © 1998, 1997, 1996, 1994, 1993, 1992, 1989

                               Russell C. Bjork

                        Professor of Computer Science

                          Gordon College, Wenham, MA

    Reproduction for non-commercial educational use is permitted; any other use
    requires permission of the author.


                            PRELIMINARY NOTE: 
                            ----------------

        The C programming language was originally developed by Dennis Ritchie in
1972.  Two major dialects of C have been available during the history of the 
language: "traditional C" (the original dialect which was distributed for many
years with all Unix systems) and ANSI C (an improved dialect standardized by 
ANSI.)  This document will describe features of both dialects.  

        An ANSI C compiler will accept programs written in traditional C (but 
not vice versa).  There still are a few C compilers that accept only traditional
C, and older books often use this dialect for example programs, so it is 
important to be aware of it.  However, since the compiler can catch certain 
common programming errors in an ANSI C program that would not be caught in a
tradtional C program, a person newly learning C is well-advised to learn the 
ANSI dialect.

        C++ is a newer language built on the base of C by Bjarne Stroustrup in 
the early 1980's. It includes several improvements to C, plus many new features 
designed to support object-oriented programming, while still retaining the basic
features of ANSI C.  As a result, a properly-written ANSI C program will be 
accepted by a C++ compiler.  (However, many traditional C programs will not be 
accepted.  Given the growing popularity of C++, this is another good reason for 
learning ANSI C rather than traditional C.)  

        C++ and its supporting libraries are currently undergoing 
standardization by ANSI/ISO, with publication of a final standard expected in
late 1998.  Currently available C++ compilers and libraries do not yet support
all of the features of this standard.

        For the most part, this handout will only describe features that are
common to both ANSI C and C++.  A few C++ features that make programming easier
or make for better programming style are also included - these are labelled
C++ only and must not be used in programs that are to be compiled by a C
compiler.  (In each case, there is an alternate C construct that serves the same
purpose.)  Finally, a few C++ features are described as new ANSI standard C++.
These may or may not be available yet in a particular C++ implementation.


Pascal                                  C/C++
------                                  -----

                        Lexical Conventions
                        ------- -----------

Not case-sensitive; upper and lower     Case-sensitive; upper and lower case
case letters are equivalent - so        letters are different - so

somename, SOMENAME, Somename, SomeName  somename, SOMENAME, Somename, SomeName  
etc. are all the same.                  are all different

--------------------------------------------------------------------------------

                            Comments
                            --------

(* This is a comment *)                 /* This is a comment */

                                        C++ only

                                        // This is a also comment - in C++ only
                                        // A comment specified this way extends
                                        // only to the end of the current line

--------------------------------------------------------------------------------

                            Constants
                            ---------

The rules for numeric constants (integer, real) are essentially the same, 
though C is a bit more flexible.  (See a C reference manual for details.)

'c'                                     'c'

'This is a string'                      "This is a string"

                                        NOTES:

                                        1. Non-printing characters may be
                                           embedded in either character or 
                                           string constants by using various
                                           escapes - e.g.

                                           \0   - null character
                                           \n   - newline
                                           \t   - tab
                                           \b   - backspace
                                           \f   - formfeed
                                           \\   - \
                                           \'   - '
                                           \"   - "
                                           \ddd - Character whose OCTAL code is
                                                  ddd - e.g. '\101' is the same 
                                                  as 'A'.

2. String constants are terminated by a null character \0. Thus, the total space allocated for a string is one more than the number of characters in it. 3. String constants may be continued over more than one line by having a \ be the very last character on the line to be continued - e.g. "This is a string constant that ex\ tends over more than one line." C++ and some ANSI C compilers only 4. A string constant may be continued over more than one line by simply closing the quotes on one line and re-opening them on the next - e.g. "This is a string constant that ex" "tends over more than one line." -------------------------------------------------------------------------------- const #define size 100 size = 100; #define pi 3.14159 pi = 3.14159; #define first 'A' first = 'A'; #define filename "XYZ.DAT" filename = 'XYZ.DAT'; ANSI C and C++ only const int size = 100; const float pi = 3.14159; const char first = 'A'; const char filename[] = "XYZ.DAT"; NOTE: In C (but not C++), an integer constant declared this way may not be used to specify the size of an array in most cases. -------------------------------------------------------------------------------- Declarations of variables ------------ -- --------- var int i; i: integer; float r; r: real; int b; b: boolean; char c; c: char; int j, k, l; j, k, l: integer; New ANSI Standard C++ bool b; NOTES: 1. C does not use a word like var to introduce variable declarations - it just declares them. 2. C does not have a separate type for boolean values. Int is used, with 0 = false and 1 = true. The new ANSI C++ standard calls for a built in type bool with values false and true, but not all C++ compilers implement it yet. 3. In addition to the scalar types shown above, C has: short int (may be abbreviated short) long int (may be abbreviated long) double (double-precision real) 4. Any integer type (including char) may be prefixed by unsigned - e.g. unsigned int i; unsigned char c; -------------------------------------------------------------------------------- var int a[10]; a: array[0..9] of integer; float b[5][10]; b: array[0..4, 0..9] of real; NOTE: Arrays in C always have subscripts ranging from 0 to declared size - 1. c: array[1..10] of integer; NO DIRECT EQUIVALENT IN C. WORK AROUND THIS BY DECLARING: int c[10]; AND LETTING SUBSCRIPTS RANGE FROM 0..9. NOTE: C does not distinguish between packed and unpacked arrays -------------------------------------------------------------------------------- var struct student: record { int id; id: integer; char name[11]; name: packed array[1..10] float gpa; of char; } student; gpa: real end; New ANSI Standard C++ In this and subsequent similar examples, the declaration of char name[11] can be replaced by: string name; The standard header <string> must be #included to allow this. -------------------------------------------------------------------------------- For this example, suppose the types employee and student have been previously declared: var union borrower: record { employee EBorr; case boolean of student SBorr; false: (EBorr: employee); } borrower; true: (SBorr: student) end; NOTE: There is no provision for an explicit tag field in C unions, analogous to the tag field of a Pascal variant record. var NO DIRECT EQUIVALENT IN C. THIS CAN borrower: record BE HANDLED BY CREATING A STRUCT WHICH case IsStudent: boolean of CONTAINS THE TAG AND A UNION AS ITS false: (EBorr: employee); FIELDS. (SEE BELOW) true: (SBorr: student) end; var struct borrower: record { id: integer; int id; name: packed array[1..10] char name[11]; of char; union case boolean of { employee EBorr; false: (EBorr: employee); student SBorr; true: (SBorr: student) } Borr; end; } borrower; We can access the variants as We can access the variants as borrower.EBorr, borrower.SBorr borrower.Borr.EBorr, borrower.Borr.SBorr C++ only: The field name Borr for the union can be omitted; the variants can then be referenced as in Pascal. -------------------------------------------------------------------------------- var enum {chocolate, vanilla} flavor; flavor: (chocolate, vanilla); NOTE: As in Pascal, it is usually better style with record and enumeration types (and often with array types) to first declare a named type and then a variable of that type. See below. -------------------------------------------------------------------------------- var squares: set of 1..9; NO DIRECT EQUIVALENT IN C. SOMEWHAT OF THE SAME EFFECT CAN SOMETIMES BE BE OBTAINED BY 1. Treating a longword as a bit vector representing of basetype size up to 32. Bitwise operations can be used to get the effect of set operations, e.g. int squares; ... squares := []; squares = 0; ... ... squares := squares + [2] squares |= 1 << 2; 2. Some C library routines allow a character string to be used like a set of char - but not as efficiently, e.g. const vowels = ['A','a','E','e', #define VOWELS "AaEeIiOoUu" 'I','i','O','o','U','u']; ... ... if c in vowels then if (strchr(VOWELS, c)) ... ... 3. Some C/C++ implementations offer library routines to implement bitsets that somewhat resemble Pascal sets. -------------------------------------------------------------------------------- NO PASCAL EQUIVALENT The type specifier for a variable may optionally be preceeded by one of the following storage class specifiers: auto, extern, register, static e.g. auto int i; extern int r; register int i; static int i; The type specifier for a function may be optionally preceeded by one of the following: static, extern, (C++ only) inline (Extern is the default for functions and top-level variables; auto is the default for local variables declared in functions.) -------------------------------------------------------------------------------- NO STANDARD PASCAL EQUIVALENT (BUT A C variable may be initialized when MANY DIALECTS ALLOW THIS) it is declared - e.g. int i = 3; char c = 'A'; float a[3] = { 1.0, 2.0, 3.0 }; struct { char name[11]; float gpa; } student = { "AARDVARK", 4.0 }; NOTE: In C++, initialization of a struct this way is not allowed if any field is of class type, requiring a constructor. Thus, in particular, this example would not work correctly if name were declared as string, since string is a library class. -------------------------------------------------------------------------------- Declarations of new types ------------ -- --- ----- type typedef float realarray[10]; realarray = array[0..9] of real; realarray a; var a: realarray; -------------------------------------------------------------------------------- type typedef struct student = record { int id; id: integer; char name[11]; name: packed array[1..10] float gpa; of char; } student; gpa: real end; student someone; var OR someone: student; struct student { int id; char name[11]; float gpa; }; struct student someone; OR struct student { int id; char name[11]; float gpa; } someone; NOTES: 1. In C, the difference between these examples is that the first creates a new type named simply 'student', while the second two create a new type whose name is 'struct student'. The third example combines the type and variable declarations into one declaration. (Compare this with the similar example under "Declarations of Variables" above, where a named type was not created.) 2. In C++, all three examples create a new type that can be called either student or struct student. -------------------------------------------------------------------------------- For this example, suppose the types employee and student have been previously declared: type typedef union borrower = record { employee EBorr; case boolean of student SBorr; false: (EBorr: employee); } borrower; true: (SBorr: student) end; borrower someone; var OR someone: borrower; union borrower { employee EBorr; student SBorr; }; union borrower someone; OR union borrower { employee EBorr; student SBorr; } someone; NOTE: See discussion of struct declarations above. -------------------------------------------------------------------------------- type typedef flavortype = (chocolate, vanilla); enum {chocolate, vanilla} flavortype; var flavortype flavor; flavor: flavortype; OR enum flavortype {chocolate, vanilla}; enum flavortype flavor; OR enum flavortype {chocolate, vanilla} flavor; NOTE: See discussion of struct declarations above. -------------------------------------------------------------------------------- Pointers -------- var int *p; p: ^integer; first: ^student; student *first; OR struct student *first; (In C, which form is used depends on whether the type student was declared using typedef or not) -------------------------------------------------------------------------------- type typedef stuptr = ^node; student *stuptr; var first: stuptr; stuptr first; OR typedef struct student *stuptr; stuptr first; (Depending, in C, on how student was declared) -------------------------------------------------------------------------------- type typedef nodeptr = ^node; struct node node = record { info: integer; int info; link: nodeptr struct node *link; end; } node, *nodeptr; var first: nodeptr; nodeptr first; OR typedef struct node * nodeptr; typedef struct node { int info; nodeptr link; } node; nodeptr first; -------------------------------------------------------------------------------- (Given the above declarations) p^ := p^ + 1; *p = *p + 1; new(first); first = (nodeptr) malloc(sizeof(node)); ... ... first := first^.link; first = first -> link; ... ... dispose(first); free(first); C++ only: first = new node; ... delete first; -------------------------------------------------------------------------------- NO PASCAL EQUIVALENT In C, the type array is equivalent to a pointer type to the element type of the array. Thus, the following pairs of operations are equivalent; either syntax can be used regardless of whether a is declared as an array or a pointer: a[0] = 1; IS EQUIVALENT TO *a = 1; a[3] = 1; IS EQUIVALENT TO *(a+3)= 1; Note that arithmetic on pointers is done in units of the size of the basetype. Thus, if ints occupy 4 bytes, then *(a+3) actually adds 12 to to calculate the desired address. Also, for formal parameters only, int a[]; IS EQUIVALENT TO int *a; As a consequence of this, the following code segments are NOT equivalent var a, b: array[0..9] of real; float a[10], b[10]; ... ... b := a; <- NOT AT ALL THE SAME -> b = a; (In fact, this would not even be syntactically legal unless b were a formal parameter of a procedure.) C allows assignment of entire structures, but NOT arrays. The equivalent C code for the Pascal array assignment is for (i=0; i < 10; i++) b[i] = a[i]; -------------------------------------------------------------------------------- Functions and Procedures --------- --- ---------- function f(x, y: integer; TRADITIONAL C: z: real): real; float f(x, y, z) int x, y; float z; var { q: integer; int q; begin q = x*x + y; q := sqr(x) + y; return q - z; f := q - z } end; ANSI C/C++: float f(int x, int y, float z) { int q; q = x*x + y; return q - z; } NOTE WELL THE DIFFERENCES IN USAGE OF SEMICOLONS BETWEEN PASCAL AND C -------------------------------------------------------------------------------- procedure p(x: integer); TRADITIONAL C: void p(x) int x; var { temp: integer; int temp; begin ... ... return; end; } ANSI C/C++: void p(int x) { int temp; ... return; } NOTE: In either dialect, the return statement is optional at the end of the code. A return statement or statements may also appear in the middle of the code. -------------------------------------------------------------------------------- Given: Given: function f: integer; int f() ... ... procedure p; void p() ... ... These routines are called by: These routines are called by: x := f; x = f(); p; p(); -------------------------------------------------------------------------------- procedure p(var x: integer); TRADITIONAL C: void p(x) int *x; begin { x := 17 *x = 17; end; } ANSI C/C++: void p(int *x) { *x = 17; } This routine is called by: In either dialect, this routine is called by: p(i); p(&i); (where i is an integer variable) (where i is an int variable) C++ only: void p(int &x) { x = 17; } Declared this way, this routine is called by: p(i); -------------------------------------------------------------------------------- type TRADITIONAL C realarray = array[0..9] of real; procedure p(var a: realarray); void p(a) float a[]; begin { a[1] := a[2] + a[3] a[1] = a[2] + a[3]; end; } OR, BECAUSE OF THE EQUIVALENCE OF ARRAYS AND POINTERS: void p(a) float *a; { a[1] = a[2] + a[3]; } ANSI C: void p(float a[]) { a[1] = a[2] + a[3]; } OR void p(float *a) { a[1] = a[2] + a[3]; } -------------------------------------------------------------------------------- function f(c: char): integer; forward; TRADITIONAL C: int f(); ANSI C/C++: int f(char c); OR int f(char); NOTE: Strictly speaking, no C dialect absolutely requires you to declare a function before it is used. If a call to a previously undeclared function is seen, the compiler assumes it is a function returning int and, in the case of ANSI C/C++, makes assumptions about the types of its formal parameters based on the types of the actual parameters appearing in the call. This serves as an implicit function declaration. However, it is always good practice to declare a function before it is used - and this is mandatory if the return type is other than int. Further, the C++ compiler (and some ANSI C compilers) issue a warning about 'implicit declaration of function' if you call a previously undeclared function. -------------------------------------------------------------------------------- function f(c: char): integer; external; TRADITIONAL C: int f(); ANSI C: int f(char c); OR int f(char); -------------------------------------------------------------------------------- program .... main() { ... ... } begin (* main program *) OR (TRADITIONAL C) ... main(argc, argv) end. int argc; char *argv[]; { ... } OR (ANSI C) main(int argc, char * argv[]) { ... } -------------------------------------------------------------------------------- Operators and Expressions --------- --- ----------- C operators are grouped in decreasing order of precedence. All operators in the same group have the same precedence. L and R indicate left and right associativity, respectively. The names used in examples stand for variables or expressions of a certain type, as follows: x, y - no particular type i, j - integers b, c - boolean p - pointer a - array or pointer s - struct f - function t - type name s.name s.name p^.name p -> name a[i] a[i] f or f(arguments ...) f() or f(arguments ...) NO PASCAL EQUIVALENT (post-increment) x++ NO PASCAL EQUIVALENT (post-decrement) x-- -------------------------------------------------------------------------------- NO PASCAL EQUIVALENT (pre-increment) ++x NO PASCAL EQUIVALENT (pre-decrement) --x p^ *p NO PASCAL EQUIVALENT (address of) &x +x (ANSI C/C++ only) +x -x -x not x !x NO PASCAL EQUIVALENT (bitwise not) ~i NO PASCAL EQUIVALENT (type cast) (t) x NO PASCAL EQUIVALENT (size in bytes) sizeof x NO PASCAL EQUIVALENT (size in bytes) sizeof (t) -------------------------------------------------------------------------------- x * y x * y L x / y x / y L i div j i / j L i mod j i % j L -------------------------------------------------------------------------------- x + y x + y L x - y x - y L -------------------------------------------------------------------------------- NO PASCAL EQUIVALENT (left shift) i << j L NO PASCAL EQUIVALENT (right shift) i >> j L -------------------------------------------------------------------------------- x < y x < y L x > y x > y L x <= y x <= y L x >= y x >= y L -------------------------------------------------------------------------------- x = y x == y L x <> y x != y L -------------------------------------------------------------------------------- NO PASCAL EQUIVALENT (bitwise and) i & j L -------------------------------------------------------------------------------- NO PASCAL EQUIVALENT (bitwise xor) i ^ j L -------------------------------------------------------------------------------- NO PASCAL EQUIVALENT (bitwise or) i | j L -------------------------------------------------------------------------------- b and c b && c L -------------------------------------------------------------------------------- b or c b || c L -------------------------------------------------------------------------------- NO PASCAL EQUIVALENT (conditional expr) b ? x : y R -------------------------------------------------------------------------------- x := y x = y R x := x + y x += y R x := x - y x -= y R x := x * y x *= y R i := i div j i /= j R x := x / y x /= y R i := i mod j i %= j R NO PASCAL EQUIVALENT (see above) i <<= j R NO PASCAL EQUIVALENT " " i >>= j R NO PASCAL EQUIVALENT " " i &= j R NO PASCAL EQUIVALENT " " i ^= j R NO PASCAL EQUIVALENT " " i |= j R -------------------------------------------------------------------------------- NO PASCAL EQUIVALENT (sequential eval) x, y L -------------------------------------------------------------------------------- The following operators are found only in C++ NO GENERAL PASCAL EQUIVALENT t(x) (type conversion) new(p) p = new t dispose(p) delete p -------------------------------------------------------------------------------- Executable Statements ---------- ---------- x := y + z x = y + z; NOTE: This is an instance of the C expression statement, which is actually much more flexible than its Pascal equivalent. The following is also legal (but contorted!) if (w += x = y++ * z) u = ++w; This is equivalent to: x = y * z; y = y + 1; w = w + x; if (w != 0) { w = w + 1; u = w; } -------------------------------------------------------------------------------- begin { x := y + z; x = y + z; w := x w = x; end } NOTES: 1. There is never a semicolon after the terminating } , but the last statement inside the compound statement does end with a semicolon. 2. The C compound statement may begin with declarations for local variables - e.g. NO PASCAL EQUIVALENT { int temp; temp = y; y = z; z = temp; } -------------------------------------------------------------------------------- if x < 0 then if (x < 0) x := -x x = -x; if x > y then if (x > y) max := x max = x; else else max := y max = y; NOTE: In C, a semicolon is a statement terminator, not a statement separator - so it MUST be used before else in a case like this. -------------------------------------------------------------------------------- while x < y do while (x < y) x := 2 * x x = 2 * x; -------------------------------------------------------------------------------- repeat do x := 2 * x; { y := y - 1 x = 2 * x; until x >= y y--; } while (x < y); NOTE: The sense of the condition is the opposite from Pascal. C is consistent about always requiring compound statements to be surrounded by braces. -------------------------------------------------------------------------------- for i := 1 to n do for (i = 1 ; i <= n ; i++) x[i] := 0 x[i] = 0; NOTE: The C for is considerably more flexible than the Pascal for. NO PASCAL EQUIVALENT USING FOR for (i = 1; i <= n; i += 10) x[i] = 0; (Zeroes x[1], x[11], x[21] .. ) NO PASCAL EQUIVALENT USING FOR for (i = 1; i <= n && x[i] != 0; i++); (Finds first element of x[] that is 0; stops if all n elements are examined without finding one.) -------------------------------------------------------------------------------- case i of switch (i) { 1: write('one'); case 1: printf("one"); 2: write('two'); break; 3: write('three'); case 2: printf("two"); 4: begin break; write('four'); case 3: printf("three"); i := 3 break; end case 4: printf("four"); i = 3; otherwise break; write('Bad value') default: printf("Bad value"); } end; NOTE: If the breaks are omitted, control flows through case to case. Thus, the following are equivalent: case i of switch(i) { 0: write('ZeroOne'); case 0: printf("Zero"); 1: write('One') case 1: printf("One"); } end; -------------------------------------------------------------------------------- if, while, repeat, for, or case if, while, do, for, or switch begin { ... ... ... ... goto 1 break; ... ... end; } 1: while, repeat, or for while, do, or for begin { ... ... ... ... goto 1; continue; ... ... 1: } end -------------------------------------------------------------------------------- procedure p ... void p( ... ... ... goto 1; return; ... ... 1: end function f ... int f( ... ... ... f := somevalue; return (somevalue); goto 1; ... ... 1: end -------------------------------------------------------------------------------- goto 1; goto fini; ... ... 1: ... fini: ... -------------------------------------------------------------------------------- ; -- the null statement ; -- the null statement -------------------------------------------------------------------------------- Input - Output ----- - ------ #include <stdio.h> var c: char; char c; i: integer; int i; r: real; float r; s: packed array[1..10] of char; char s[10]; ... ... read(c); scanf("%c", & c); read(i); scanf("%d", & i); read(r); scanf("%f", & r); NO STANDARD PASCAL EQUIVALENT scanf("%s", s); readln; while (getchar() != '\n') ; readln(c, i, r); scanf("%c%d%f", & c, & i, & r); while (getchar() != '\n') ; write(c); printf("%c", c); write(i); printf("%d", i); write(r); printf("%f", r); write(s); printf("%s", s); writeln; printf("\n"); writeln('c=',c,' i=',i,' r=', r, s); printf("c=%c i=%d r=%f%s\n",c, i, r, s); C++ only: #include <iostream.h> cin >> c; cin >> i; cin >> r; cin >> s; while (cin.get() != '\n') ; cin >> c, i, r; while (cin.get() != '\n') ; cout << c; cout << i; cout << r; cout << s; cout << endl; cout << "c=" << c << " i=" << i << " r=" << r << s << endl; -------------------------------------------------------------------------------- (* Other variables declared as above *) /* Other variables declared as above */ fi, fo: text; FILE * fi, * fo; (* fi will be opened for input, /* fi will be opened for input, fo will be opened for output *) fo will be opened for output */ ... ... readln(fi, c, i, r); fscanf(fi, "%c%d%f", & c, & i, & r); while (fgetc(fi) != '\n') ; writeln(fo,'c=',c,' i=',i,' r=',r, s); fprintf(fo,"c=%c i=%d r=%f%s\n", c,i,r,s); C++ only: #include <fstream.h> ifstream fi; ofstream fo; fi >> c >> i >> r; while (fi.get() != '\n') ; fo << "c=" << c << " i=" << i << " r=" << r << s << endl; NOTE: One minor difference in the above is that Pascal read and C scanf() do NOT skip leading whitespace when reading into a char, but C++ >> does. (However, C++ get() does not skip whitespace.) Order of Program Parts ----- -- ------- ----- In standard Pascal, a program A C/C++ program consists of a series of consists of a program header, declarations/definitions, which can followed by a block, followed by a appear in any order (so long as period - all residing in a single items are declared before they are source file. A block, in turn used when necessary.) A C/C++ program consists of the following parts, of any significant size is almost in the order listed: always spread out over multiple source files. (optional) label declaration(s) (optional) const declaration(s) A function definition consists of a (optional) type declaration(s) header followed by a compound statement. (optional) var declaration(s) (optional) function/procedure Declarations of variables (including declaration(s) const variables) can appear at the (required) compound statement start of any compound statment. A function/procedure declaration Example: consists of a header, followed by a block, followed by a semicolon - if (x > y) thus blocks can be nested within { int z; blocks. scanf("%d", &z); x = z + 32; Many Pascal implementations relax } these requirements to allow, for example: However, declarations of functions may not appear inside the definition of 1. Declarations to appear in any another functions - thus function order or mixture. definitions cannot be nested as in Pascal. 2. A program to be spread out over multiple source files. C++ only: Variable declarations can appear anywhere within a compound statement - not just at the start, and can also appear in the first part of the control portion of a for statement. Example: main() { cout << "How many times? "; int times; cin >> times; for (int i = 1; i <= times; i++) cout << "Hello, world!" << endl; } The C/C++ Pre-processor --- ----- ------------- C and C++ compilers include a pre-processor that performs certain modifications on the program text BEFORE the compiler proper sees it. The following are examples of pre-processor directives found in typical C/C++ implementations, though some do not have all of these and some may have more. Note the similarity between the macro facility typically found in assemblers and the C/C++ pre-processor's #define and #if/#ifdef directives. const size = 10 #define size 10 NO PASCAL EQUIVALENT #define iszero(e) (e == 0) NO PASCAL EQUIVALENT #define equal(x, y) (x == y) NO PASCAL EQUIVALENT #define error(f, m) if (f) \ printf(m) NO PASCAL EQUIVALENT #define VAX NO PASCAL EQUIVALENT #undef VAX NO PASCAL EQUIVALENT #if wordlength >= 32 typedef int myint; #else typedef long myint; #endif NO PASCAL EQUIVALENT #ifdef VAX ... VAX-specific code #endif NO PASCAL EQUIVALENT #ifndef size #define size 100 /* default */ #endif -------------------------------------------------------------------------------- C and C++ make extensive use of header files incorporating declarations for constants, data, and code to support splitting a program across multiple source files. The #include directive is used to incorporate the contents of a header file into a source program. NO PASCAL EQUIVALENT #include <stdio.h> NO PASCAL EQUIVALENT #include "myinclude.h" NOTE: The <filename> form is used for standard header files defining C/C++ library routines, which reside in a system directory; the "filename" form is used for programmer-written header files normally residing in the same directory as the program being compiled. A common practice in C/C++ is to implement a "module" as two files - a header (.h) file containing declarations that clients of the module need to use, and an implementation (.c/cc) file that defines the entities declared in the header. Clients of the module #include the header, and the compiled version of the implementation is included into the executable when the program is linked.