Примеры не раздельной компиляции?
Из раздела 1.1 "Книги С":
На самом грубом уровне очевидной особенностью является многофайловая структура программы. Язык допускает отдельную компиляцию, где части полной программы могут храниться в одном или нескольких исходных файлах и компилироваться независимо друг от друга. Идея состоит в том, что процесс компиляции создаст файлы, которые затем могут быть связаны вместе с помощью любого редактора ссылок или загрузчика, который предоставляет ваша система. Блочная структура Algol-подобных языков усложняет задачу, настаивая на том, что вся программа состоит из одного фрагмента, хотя обычно есть способы обойти это.
Может ли кто-нибудь предоставить некоторые основные примеры / обзор программирования в этой природе?
3 ответа
Пример программы Algol, которая не делает ничего полезного, но здесь для иллюстрации:
begin
int x; x:=3;
procedure p;
begin
integer y; y:=4;
procedure q(n);
value n; integer n;
if n > 0
then q(n-1)
else begin
integer z; z:=x+y;
print(z)
end;
q(1)
end;
p; comment a parameterless procedure call;
end;
Основная проблема здесь - вложенные области видимости. Процедура q
зависит от окружающих блоков, которые определяют целые числа x
а также y
, Процедура p
также зависит (в силу содержания q
) на блоке, который определяет x
,
Итак, вы увидите, что каждая часть этой глупой программы-примера неотделима от окружающего текста. Это естественный способ выражения для Алголеров; вкладывать процедуры так, чтобы это имело смысл для написанной программы. В целом это делает отдельную компиляцию довольно сложной. Это отличается от C-подобных языков, которые не имеют вложенных процедур (функций и т. Д.), Потому что единственные нелокальные идентификаторы, на которые они могут ссылаться, это область файла или глобальная область (если я правильно понимаю эти термины).
Здесь переменные x
а также y
являются локальными для некоторой процедуры и поэтому находятся в стеке. Просто чтобы сделать это более сложным, q
является рекурсивным, что делает "расстояние вниз по стеку" от его внутреннего вызова до местоположений x
а также y
переменное количество, так что это не просто вопрос компиляции фиксированного значения из некоторого указателя кадра стека.
Тем не менее, были некоторые системы, которые допускали отдельную компиляцию Насколько я помню, были ограничения, такие как единица компиляции (если хотите, файл), которая должна содержать только процедуры "на верхнем уровне". Возможно, им также понадобился некоторый расширенный синтаксис (например, "внешняя процедура foo"), чтобы сообщить компилятору, что в текущем файле не должно быть определено что-то, на что ссылаются.
Самый маленький пример не раздельной компиляции, один файл m.c
содержащий:
int main() {}
компиляция: gcc m.c
производя исполняемый файл a.out
В C мы можем поместить все в один файл или несколько файлов, а также скомпилировать за один или несколько шагов, если это ваш вопрос
Пример с двумя функциями в отдельном файле m.c
:
#include <stdio.h>
void hw()
{
puts("hello world");
}
int main()
{
hw();
}
Компиляция, мы также можем сделать в один или несколько шагов
gcc m.c
производя исполняемый файлa.out
- или же
gcc -c m.c
производстваm.o
затемgcc m.o
создание исполняемого файлаa.out
Та же программа, использующая несколько файлов, hw.c
содержащий
#include <stdio.h>
#include "hw.h" /* not mandatory in current case but recommended to check signature compatibility */
void hw()
{
puts("hello world");
}
а также hw.h
содержащий
#ifndef _HW_H
#define _Hw_H
extern void hw();
#endif
а также m.c
содержащий
#include "hw.h"
int main()
{
hw();
}
Компиляция, используя один или несколько шагов:
gcc m.c hw.c
создание исполняемого файлаa.out
- или же
gcc -c m.c hw.c
производство объектовm.o
а такжеhw.o
, затемgcc m.o hw.o
производить исполняемый файлa.out
- или же
gcc -c m.c
производство объектовm.o
затемgcc -c hw.c
производящий объектhw.o
затемgcc m.o hw.o
производить исполняемый файлa.out
Также можно создать и использовать библиотеку, здесь статическая библиотека, содержащая только hw.o
:
gcc -c m.c hw.c
производство объектовm.o
а такжеhw.o
(или две команды gcc, одна за объектом)ar rcs hw.a hw.o
сделать статическую библиотеку, содержащуюhw.o
gcc m.o hw.a
произвести исполняемый файлa.out
Я не уверен, что книга подразумевает под "блочной структурой алголоподобных языков, это усложняет задачу, настаивая на том, что вся программа состоит из одного куска". Но я могу себе представить, что Algol-подобный язык разрешает или требует, чтобы функции и процедуры были объявлены в основном программном блоке, подразумевая, что существует только один программный блок, и это не позволит разделить программу на скомпилируемые блоки, как это делает C. Но опять же, я не знаю, что означает книга с этим утверждением.
Гипотетический пример:
AlgolMain
Begin
procedure x
Begin
....
End
....
End
Может ли кто-нибудь предоставить некоторые основные примеры / обзор программирования в этой природе?
Один файл называется add.c
который содержит следующий код:
int add(int a, int b){
return a+b;
}
Скомпилируйте это с:
gcc -c add.c
Это создает add.o
, Теперь есть файл со следующим кодом main.c
:
#include <stdio.h>
int add(int, int); // declares "add", but doesn't implement it!
int main( int argc, char **argv){
printf("3 + 2 = %d\n", add(3,2));
return 0;
}
Это заявляет add
, но не реализует это. Он не будет работать сам по себе. Но вы все равно можете скомпилировать его с
gcc -c main.c
И тогда вы можете связать их с:
gcc add.o main.o
Если вы запустите результирующую программу (которая может называться a.exe` или что-то подобное), вы получите следующий результат:
3 + 2 = 5
Преимущество этого состоит в том, что вы можете изменить одну из частей, перекомпилировать ее, а затем снова связать, не касаясь других частей. Если вы хотите более подробное объяснение по этому вопросу, я рекомендую прочитать этот ответ.