Страница 15 из 56
end; }
----------------------------------------------------------------
Заметим, что в Си оператор return используется для возвраще-
ния значения функции, в то время как в Паскале это достигается
присвоением значения имени функции.
Турбо Паскаль Турбо Си
-----------------------------------------------------------------
procedure Swap(var X,Y : Real); void swap(float *x, float *y)
var
Temp : Real; {
begin float temp;
Temp := X; temp= *a;
X := Y; *a = *b;
Y := Temp *b = temp;
end; }
-----------------------------------------------------------------
B Паскале имеется 2 типа параметров:var (передача по адресу)
и value (по значению). В Си параметры передаются только по значе-
нию. Если вы хотите иметь параметры, передаваемые по адресу, то
вы должны передавать адрес, а формальный параметр определить как
указатель. Это было продемонстрировано в вышеприведенном примере
функции swap. Ниже приведена программа вызова этих подпрограмм:
- 119,120 -
Турбо Паскаль Турбо Си
----------------------------------------------------------------
Q := 7.5; g = 7.5;
R := 9.2; r = 9.2;
Writeln('Q=',Q:5:1,'R=',R:5:1); printf("g=%5.1f r=%5.1f\n",g,r);
Swap(Q,R); swap(&g,&r);
Writeln('Q=',0:5:1,'R=',R:5:1); printf("g=%5.1f r=%5.1f\n",g,r);
-----------------------------------------------------------------
Отметим использование операции адреса (&) в Си при передаче
параметров g и r подпрограмме swap.
Прототипы функций.
-----------------------------------------------------------------
Наиболее важные различия между Паскалем и Си касаются функ-
ций: Паскаль всегда делает проверку на соответствие количества и
типов параметров, определенных в функции, с количеством и типами
параметров, используемых при вызыве этой функцией. Другими слова-
ми, допустим вы определили функцию:
function Max(I,J : Integer) : Integer;
и пытаетесь вызвать ее с действительными значениями
(А:=Мах(В,3.52);). Что произойдет? Вы получите при трансляции
ошибку, сообщающую вам, что присутствует несоответствие типов, т.
к. 3.52 не является целым.
В Си это не так, по умолчанию Си-компилятор не производит
проверку ошибок при вызове функции: он не проверяет возвращаемые
функцией параметры, их типы и количество. С одной стороны - это
дает некоторую свободу, так как можно вызывать функцию до того,
как она будет определена, с другой - может причинить и беспокойс-
тво (см. "Ошибку #2" в заключении главы). Можно ли это как-то из-
- 121,122 -
бежать?
Турбо Си поддерживает прототипы функций. Вы можете понимать
это, как нечто подобное предварительному описанию в Паскале. Ста-
райтесь располагать прототипы функций в начале текста программы
(перед вызовом этих функций). Запомните, что прототип функции -
является видом описания и должен предшествовать фактическому вы-
зову функции. Прототип функции имеет формат:
int max(int a, int b);
void swap(float *x, float *y);
void swapitem (listitem *i, listitem *j);
void sortlist (list l, int c);
void dumplist (list l, int c);
В отличие от оператора предварительного описания - forward у
Паскаля, прототипы функций в Си освобождают вас от лишних усилий
при фактическом определении функции. Другими словами вы можете
определить функцию как вам хочется (или определить ее, используя
современный стиль программирования). Конечно, если описание функ-
ции не будет соответствовать прототипу, Турбо Си выдаст ошибку
компиляции.
Турбо Си поддерживает и классический, и современный стиль,
однако сейчас в Си тенденция к использованию нового стиля, поэто-
му и мы рекомендуем вам применять прототипы функций.
Использование прототипов функций помогает избежать некоторых
проблем, особенно, когда вы используете оттранслированные библио-
теки Си программ. Вы можете создать отдельный файл и ввести в не-
го заголовки функций всех подпрограмм из библиотеки. Когда вы за-
хотите использовать любую программу из библиотеки, включите ваш
заголовок файла в программу (с помощью директивы #include). Такой
способ поможет вам избежать неприятностей от возможной ошибки во
время трансляции.
- 123,124 -
Основной пример.
-----------------------------------------------------------------
Теперь приведем большой пример, целую программу, использую-
щую многое из того, что вы узнали до сих пор. Программа определя-
ет массив myList, длина которого - LMAX, а тип (List Item) соот-
ветствует целому. Массив инициализируется неупорядоченными числа-
ми, выводится на дисплей подпрограммой dumplist, сортируется по
порядку с помощью sortlist, и снова выводится на дисплей.
Отметим, что данная Си версия программы не самая лучшая. Она
была написана в максимально возможном приближении к версии на
Паскаль. Некоторые места, которые не соответствуют друг другу,
демонстрируют коренные различия Си и Паскаля.
Турбо Паскаль Турбо Си
----------------------------------------------------------------
program DoSort;
const
LMax = 100; #define LMAX 100
type
Item = Integer; typedef int item;
List = array[1..LMax] of Item; typedef item list[LMAX];
var
myList : List; list myList;
Count,I : Integer; int count, i;
Ch : Char; char ch;
procedure SortList(var L:List; void swapitem(item *i,item*j)
C : Integer);
var {
Top,Min,K : Integer; item temp;
temp = *i; *i = *j; *j =temp;
procedure SwapItem(var I,J:Item); } /* swapitem */
var
Temp : Item; void sortlist(list l, int c)
begin
Temp:=I; I:=J; J:=Temp
end; (*конец SwapItem*)
{
int top,min,k;
begin (*Основное тело SortList*)
for Top:=l to C-1 do begin for(top=0; top<=c; k++)
if L[K]< l[min])
then Min := K; min = k;
SwapItem(L[Top],L[Min]) swapitem(&l[top],&l[min]);
end }
end;(*конец SortList*) }/*sortlist*/
procedure DumpList(L:List; void dumplist(list l,int c)
C : Integer);
var
I : Integer; {
begin int i;
for I := l to C do for (i=0; i<=c; i++)
Writeln('L(',I:3,')=',L[I]:4) printf("l/%3d)=%4d\n",i,l[i]);
end; (*Конец DumpList*) } /* dumplist()*/
main()
begin (*Основное тело DoSort*) {
for I := l to LMax do for (i=0; i