The computer programming languages C and Pascal have similar times of origin, influences, and purposes. Both were used to design (and compile) their own compilers early in their lifetimes. The original Pascal definition appeared in 1969 and a first compiler in 1970. The first version of C appeared in 1972.
Both are descendants of the ALGOL language series. ALGOL introduced programming language support for structured programming, where programs are constructed of single entry and single exit constructs such as if, while, for and case. Pascal stems directly from ALGOL W, while it shared some new ideas with ALGOL 68. The C language is more indirectly related to ALGOL, originally through B, BCPL, and CPL, and later through ALGOL 68 (for example in case of struct and union) and also Pascal (for example in case of enumerations, const, typedef and Booleans). Some Pascal dialects also incorporated traits from C.
The languages documented here are the Pascal designed by Niklaus Wirth, as standardized as ISO 7185 in 1982, and the C designed by Dennis Ritchie, as standardized as C89 in 1989. The reason is that these versions both represent the mature version of the language, and also because they are comparatively close in time. ANSI C and C99 (the later C standards) features, and features of later implementations of Pascal (Turbo Pascal, Free Pascal etc.) are not included in the comparison, despite the improvements in robustness and functionality that they conferred e.g. Comparison of Pascal and Delphi
Syntax
Syntactically, Pascal is much more ALGOL-like than C. English keywords are retained where C uses punctuation symbols – Pascal has and, or, and mod where C uses &&, ||, and % for example. However, C is more ALGOL-like than Pascal regarding (simple) declarations, retaining the type-name variable-name syntax. For example, C can accept declarations at the start of any block, not just the outer block of a function.
Semicolon use Another, more subtle, difference is the role of the semicolon. In Pascal, semicolons separate individual statements within a compound statement; instead in C, they terminate the statement. In C, they are also syntactically part of the statement (transforming an expression into a statement). This difference manifests mainly in two situations:
in Pascal, a semicolon can never be directly before else, whereas in C, it is mandatory, unless a block statement is used the last statement before an end or until is not required to be followed by a semicolon
A superfluous semicolon can be put on the last line before end, thereby formally inserting an empty statement.
Comments In the first edition of C, there are only /* block comments */. C later added // line comments.
In Pascal, there are { block comments } and (* block comments *).
Identifiers and keywords C and Pascal differ in their interpretation of upper and lower case. C is case sensitive while Pascal is not, thus MyLabel and mylabel are distinct names in C but identical in Pascal. In both languages, identifiers consist of letters and digits, with the rule that the first character may not be a digit. In C, the underscore counts as a letter, so even _abc is a valid name. Names with a leading underscore are often used to differentiate special system identifiers in C.
Both C and Pascal use keywords (words reserved for use by the language). Examples are if, while, const, for and goto, which are keywords that happen to be common to both languages. In C, the basic built-in type names are also keywords (e.g., int, char) or combinations of keywords (e.g., unsigned char), while in Pascal the built-in type names are predefined normal identifiers.
Definitions, declarations, and blocks In Pascal, subroutine definitions start with keywords procedure (no value returned) or function (a value is returned) and type definitions with type. In C, all subroutines have function definitions (procedures being void functions) and type definitions use the keyword typedef. Both languages use a mix of keywords and punctuation for definitions of complex types; for instance, arrays are defined by the keyword array in Pascal and by punctuation in C, while enumerations are defined by the keyword enum in C but by punctuation in Pascal.
In Pascal subroutines, begin and end delimit a block of statements preceded by local declarations, while C functions use "{" and "}" to delimit a block of statements optionally preceded by declarations : C (before C99) strictly defines that any declarations must occur before the statements within a particular block but allows blocks to appear within blocks, which is a way to go around this. By its syntax of a subroutine's body, Pascal enforces that declarations occur before statements. Pascal also allows definitions of types and functionsnot only variable declarations to be encapsulated by function definitions to any level of depth.
Implementation The grammars of both languages are of a similar size. From an implementation perspective the main difference between the two languages is that to parse C it is necessary to have access to a symbol table for types, while in Pascal there is only one such construct, assignment. For instance, the C fragment X * Y; could be a declaration of Y to be an object whose type is pointer to X, or a statement-expression that multiplies X and Y. In contrast, the corresponding Pascal fragments var Y : ^X; and Z := X * Y; are inherently unambiguous; correct parsing does not require a symbol table.
Simple types
Integers Pascal requires all variable and function declarations to specify their type explicitly. In traditional C, a type name may be omitted in most contexts and the default type int (which corresponds to integer in Pascal) is then implicitly assumed (however, such defaults are considered bad practice in C and are often flagged by warnings).
C accommodates different sizes and signed and unsigned modes for integers by using modifiers such as long, short, signed, unsigned, etc. The exact meaning of the resulting integer type is machine-dependent, what can be guaranteed is that long int is no shorter than int and int is no shorter than short int. However, in C standard, there are at least minimal sizes of types are specified which guarantees char to be a single byte and int to be at least two bytes.
Subranges In Pascal, a similar end is performed by declaring a subrange of integer (a compiler may then choose to allocate a smaller amount of storage for the declared variable):
type a = 1..100; b = -20..20; c = 0..100000;
This subrange feature is not supported by C.
A major, if subtle, difference between C and Pascal is how they promote integer operations. In Pascal, the result of an operation is defined for all integer/subrange types, even if intermediate results do not fit into an integer. The result is undefined only if it does not fit into the integer/subrange on the left hand side of the assignment. This may imply an artificial restriction on the range of integer types, or may require slow execution to handle the intermediate results: However, the compiler may take advantage of restricted subranges to produce more efficient code.
In C, operands must first be promoted to the size of the required result: intermediate results are undefined if they do not fit into the range of the promoted operands. If range of the required result is greater than the range of operands, this normally produces slow inefficient code, even from a good optimising compiler. However, a C compiler is never required or expected to handle out of range intermediate results: it is the programmers responsibility to ensure that all intermediate results fit into the operand range.
Pre-Standard implementations of C as well as Small-C et al. allowed integer and pointer types to be relatively freely intermixed.
Character types In C the character type is char which is a kind of integer that is no longer than short int, . Expressions such as 'x' + 1 are therefore perfectly legal, as are declarations such as int i = 'i'; and char c = 74;.
This integer nature of char (one byte) is clearly illustrated by declarations such as unsigned char uc = 255; // common limit signed char sc = -128; // common negative limit
Whether the char type should be regarded as signed or unsigned by default is up to the implementation.
In Pascal, characters and integers are distinct types. The inbuilt compiler functions ord() and chr() can be used to typecast single characters to the corresponding integer value of the character set in use, and vice versa. e.g. on systems using the ASCII character set ord('1') = 49 and chr(9) is a TAB character.
Boolean types In Pascal, boolean is an enumerated type. The possible values of boolean are false and true, with ordinal value of false = 0 and true = 1. For conversion to integer, ord is used:
i := ord(b);
There is no standard function for integer to boolean, however, the conversion is simple in practice:
b := i <> 0;
C has a Boolean type, bool, since C23, but did not have one prior. C uses binary valued relational operators (<, >, ==, !=, <=, >=) which may be regarded as Boolean in the sense that they always give results that are either zero or one. As all tests (&&, ||, ?:, if, while, etc.) are performed by zero-checks, false is represented by zero, while true is represented by any other value. This is visible in the bool numeric datatype defined in <stdbool.h> (pre-C23).
Bitwise operations C allows using bitwise operators to perform Boolean operations. Care must be taken because the semantics are different when operands make use of more than one bit to represent a value.
Pascal has another more abstract, high-level method of dealing with bitwise data, sets. Sets allow the programmer to set, clear, intersect, and unite bitwise data values, rather than using direct bitwise operators. Example;
Pascal: Status := Status + [StickyFlag]; Status := Status - [StickyFlag]; if (StickyFlag in Status) then ...
C: Status |= StickyFlag; Status &= ~StickyFlag; if (Status & StickyFlag) { ...
Although bit operations on integers and operations on sets can be considered similar if the sets are implemented using bits, there is no direct parallel between their uses unless a non-standard conversion between integers and sets is possible.
A note on implementation During expression evaluation, and in both languages, a Boolean value may be internally stored as a single bit, a single byte, a full machine word, a position in the generated code, or as a condition code in a status register, depending on machine, compiler, and situation; these factors are usually more important than the language compiled.
Floating point types C has a less strict model of floating point types than Pascal. In C, integers may be implicitly converted to floating point numbers, and vice versa (though possible precision loss may be flagged by warnings). In Pascal, integers may be implicitly converted to real, but conversion of real to integer (where information may be lost) must be done explicitly via the functions trunc() and round(), which truncate or round off the fraction, respectively.
Enumeration types Both C and Pascal include enumeration types. A Pascal example:
type color = (red, green, blue); var a: color;
A C example:
enum Color { RED, GREEN, BLUE
enum Color a = RED;