Converting Pascal to C

I'm no expert at C (hence I wrote this guide for my own education) so please take every care when reading it. I've checked most of it, but please refer to a formal C reference before assuming it is correct. And feel free to point out any errors, no matter how trivial. I also welcome suggestions for additional material; there's a mailto at the bottom of this page. My thanks to the anonymous person from Bell Canada for many helpful observations.

C is case-sensitive. That is, the identifier myVar is different to myvar, whereas in Pascal they would be the same.

Comments

{ ... }

and

(* ... *)

are replaced by

/* ... */

Use

// ...

for a single-line comment, which is not available in Pascal.

Types

Pascal's type has no equivalent in C.


type myType = integer;

becomes

typedef myType int;

For Pascal records (C structs), it is a little more complicated:

date_t = record
   date : integer;
   month : integer;
   year : integer;
end;

becomes

struct date_tag {
   int date;
   int month;
   int year;
};

but it doesn't end there since the date_rec_tag is not actually a type in C. There is another step required to create a type for a structure in C.


In Pascal, the identifier associated with a record definition becomes a stand-alone type. However, in C, the identifier is only a subsititute for the structure—it does not actually become a type. It is actually known as a structure tag. To define a type for a structure, add the following:

typedef struct date_tag date_t

Constants

const x = 10;

is replaced by

#define x 10

(note there is no terminating semi-colon). Also, ANSI C allows the following constant declaration:

const int x = 10;

Variables

var

has no equivalent in C. Variables can be declared anywhere.

The format for a var declaration is simpler in C:

var x : integer;

becomes

int x;

Expressions

Pascal's

Inc(x);

routine is replaced with

x++;

where X is incremented after other operations, a behaviour known as post-increment, the pre-increment behaviour is invoked by:

++x;

You can also use the following syntax:

x += 1;

C does not handle expressions like float = (integer / integer) very well, in that it forces the type of the result to the type that best handles the result. For instance, from the code:

int intX;
int intY;
float fltZ;

fltZ = intX / intY;

The order is char, int, long, float, double. The compiler uses the earliest in the order that still handles the result. To obtain a floating-point result, use typecasting, thus:

fltZ = (float)intX / (float)intY;

Case Statement

Pascal's case statement is somewhat different in C. The following:

case key of
27: writeln( 'Escape key pressed' );
13: writeln( 'Tab key pressed' );
else
   writeln( 'Unrecognised key pressed' );
end;

becomes

switch (key) {
   case 27:
      printf( "Escape key pressed\n" );
      break;
   case '9':
      printf( "Tab key pressed\n" );
      break;
   default;
      printf( "Unrecognised key pressed\n" );
   }

Note that you have to use the break statement to end execution for a particular case; if you don't use it, the following case(s) will also be executed until either a break statement or the closing brace is encountered.

Conditionals

if x = 1 then y = 3;

becomes

if (x == 1) y = 3;

in C. Note that brackets are required around the condition, and note also the difference between the assignment = and equality == operators.

WARNING: Pascal's assignment (‘becomes’) operator := is a single equals sign in C: =. The equality operator is a single equals sign for Pascal and a double equals sign in C ==. This is a cause of a common bug—it is very easy to accidentally write something like this:

if (x = 1) doSomething();

The problem with this statement is that it will always be true, since the single equals is an assignment operator, and the asiignment operator always returns a result of ‘true’, hence the doSomething() function would always be called.


Pascal's logical operators are different thus:

or

becomes

||

whilst

and

becomes

&&

The inequality test (not equal to) in Pascal is

<>

but in C, it is

!=

Loops

Pascal's

repeat ... until <condition>;

is replaced by

do { ... } while (<condition>);

Pascal's

while, begin ... end

TODO


Because C's implementation of the for statement allows the programmer to specify the operation and tests that is performed at each loop, and the variables in these operations need not have any relation to each other, it is very flexible and can be used in many situations. In contrast, Pascal's for loop only considers the value of the given index variable for the start and end conditions, and only increments the same variable.

for x = 1 to 100
   begin
   end;

becomes

for (x = 1; x <= 100; x++ )
   {
   }

The first statement sets the starting value of the loop variable, whilst the second statement is not a terminating condition, but a continuation condition. Finally, the last statement is performed with each iteration of the loop; in this case, we merely increment the loop variable by one, but we could put anything in there.

Procedures

In C, all subroutines are functions, which can return values. To emulate Pascal's procedure (i.e. a subroutine that does not return a value), just ignore the return value. Thus,

procedure myProcedure( myInt : integer );

becomes

void myProcedure( int myInt )

The initial void is the return type for the function; in this case, no value is returned hence void. Note that the C does not terminate the function name header with a semicolon.

If a C function does not take any input parameters, the parameter list should be declared void, for instance:

void myProcedure( void )

The begin end pair that contain the code for a routine are replaced with the curly brackets for C. Also, variables that are local to the routine should be declared within the curly braces, unlike Pascal, where the vars appear before the begin end pair. Thus:

procedure myProcedure();
var
   myInt : integer;
begin
   ...
end;

becomes

void myProcedure(void)
{
   int myInt;
   ...
}

Execution of a C function (that doesn't return a value) is ended with:

return;

There can be more than one return statement in a routine, but the last statement is usually a return. The return is optional if the function doesn't return a value.

Functions

The return value of a Pascal function is specified by assigning the value to the function's name within the function itself. However, in C, the value is returned with the return statement thus:

function myFunction() : integer;
var
   myInt : integer;
begin
   ...
   myFunction = myInt;
end;

becomes

int myFunction( void )
{
   int myInt;
   return myInt;
}

Parameters

Parameter passing frequently uses pointers; pointers in C are (in my opinion) very confusing, so see the page on pointers and dynamic memory for more confusion information ;-).

To pass by value:

procedure myProcedure( myVar : integer );

becomes

void myProcedure( int myVar )

This enables the function to change the value of myVar (the formal parameter) within the function without changing the value of the corresponding (actual) parameter in the caller. To refer to the address of myVar in the function, use the & operator. For example:

void myProcedure( int myVar )
{
   printf( "myVar's value = %d\n", myVar );
   printf( "myVar's memory address = %x\n", &myVar );
}

If, in contrast, the function must change the value of a parameter as stored by its caller, the formal parameter (i.e. the variable identifier in the function header) must be prefixed with the * operator, so that it is passed by reference, thus:

void myProcedure( int *myVar )
{
   printf( "myVar's value = %d\n", *myVar );
   printf( "myVar's memory address = %x\n", myVar );
}

Note that the references to the variable inside the function have to be changed; when the input parameter is passed by reference (i.e. an address), its value is obtained by prefixing its identifier with an asterisk, whilst its address is obtained directly (without any prefix).

Essentially, to make a C parameter a Pascal var parameter, turn it into a pointer by prepending an asterisk. Within the function, refer to the value also by prepending an asterisk.

In the caller, the function call must use the address of the variable.

void myCaller( void )
{
   int myInt;

   myInt = 99;
   printf( "myInt before = %d\n", myInt );
   myProcedure( myInt* );
   printf( "myInt after = %d\n", myInt );
}


Home About Me
Copyright © Neil Carter

Content last updated: 2012-07-12