非独立编译的例子?
Examples of non-separate compilation?
来自 "The C Book" 的第 1.1 节:
At the coarsest level, an obvious feature is the multi-file structure
of a program. The language permits separate compilation, where the
parts of a complete program can be kept in one or more source files
and compiled independently of each other. The idea is that the
compilation process will produce files which can then be linked
together using whatever link editor or loader that your system
provides. The block structure of the Algol-like languages makes this
harder by insisting that the whole program comes in one chunk,
although there are usually ways of getting around it.
任何人都可以提供一些基本示例/这种性质的编程概述吗?
非单独编译的最小示例,单独的文件 m.c
包含:
int main() {}
编译:gcc m.c
生成可执行文件a.out
在 C 中,我们可以自由地将所有内容放在一个文件或多个文件中,也可以在一个或多个步骤中编译,如果这是您的问题
单独文件中有 2 个函数的示例 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
Can anyone provide some basic examples / overview of programming in
this nature ?
有一个名为 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
然后你可以link他们:
gcc add.o main.o
如果您 运行 生成的程序(可能称为 a.exe` 或类似名称),您将得到以下结果:
3 + 2 = 5
这样做的好处是您可以修改其中一个部分,重新编译它,然后 link 再次编译它,而不必触及其他部分。如果您想对此事进行更详细的解释,我建议您阅读 this answer.
我不确定这本书是什么意思 "The block structure of the Algol-like languages makes this harder by insisting that the whole program comes in one chunk." 但我可以想象,类似 Algol 的语言允许或要求声明函数和过程 在 主程序块内,意味着只有一个程序块,这将不允许将程序划分为可编译单元,就像 C 那样。但同样,我不知道这本书中的那句话是什么意思。
假设示例:
AlgolMain
Begin
procedure x
Begin
....
End
....
End
示例 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
.
的块
然后,您将看到这个愚蠢的示例程序的每个部分都与周围的文本密不可分。这是 Algolers 的自然表达方式;以对正在编写的程序有意义的方式嵌套过程。一般来说,这会使单独的编译变得相当复杂。这不同于没有嵌套过程(函数等)的 C-like 语言,因为它们可以引用的唯一 non-local 标识符是文件范围或全局范围(如果我的这些术语正确的话)。
这里,变量 x
和 y
是某些过程的局部变量,因此在堆栈上。只是为了让它更复杂,q
是递归的,这使得 "distance down the stack" 从它的最内层调用到 x
和 y
的位置是一个可变的数量,所以它不仅仅是从一些 stack-frame 指针编译一个固定值的问题。
然而,有些系统允许单独编译。据我所知,有一些限制,例如编译单元(一个文件,如果你愿意的话)必须只包含过程 'at the top level'。他们可能还需要一些扩展语法(如 'external procedure foo')来告诉编译器所引用的内容不应在当前文件中定义。
来自 "The C Book" 的第 1.1 节:
At the coarsest level, an obvious feature is the multi-file structure of a program. The language permits separate compilation, where the parts of a complete program can be kept in one or more source files and compiled independently of each other. The idea is that the compilation process will produce files which can then be linked together using whatever link editor or loader that your system provides. The block structure of the Algol-like languages makes this harder by insisting that the whole program comes in one chunk, although there are usually ways of getting around it.
任何人都可以提供一些基本示例/这种性质的编程概述吗?
非单独编译的最小示例,单独的文件 m.c
包含:
int main() {}
编译:gcc m.c
生成可执行文件a.out
在 C 中,我们可以自由地将所有内容放在一个文件或多个文件中,也可以在一个或多个步骤中编译,如果这是您的问题
单独文件中有 2 个函数的示例 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
Can anyone provide some basic examples / overview of programming in this nature ?
有一个名为 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
然后你可以link他们:
gcc add.o main.o
如果您 运行 生成的程序(可能称为 a.exe` 或类似名称),您将得到以下结果:
3 + 2 = 5
这样做的好处是您可以修改其中一个部分,重新编译它,然后 link 再次编译它,而不必触及其他部分。如果您想对此事进行更详细的解释,我建议您阅读 this answer.
我不确定这本书是什么意思 "The block structure of the Algol-like languages makes this harder by insisting that the whole program comes in one chunk." 但我可以想象,类似 Algol 的语言允许或要求声明函数和过程 在 主程序块内,意味着只有一个程序块,这将不允许将程序划分为可编译单元,就像 C 那样。但同样,我不知道这本书中的那句话是什么意思。
假设示例:
AlgolMain
Begin
procedure x
Begin
....
End
....
End
示例 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
.
然后,您将看到这个愚蠢的示例程序的每个部分都与周围的文本密不可分。这是 Algolers 的自然表达方式;以对正在编写的程序有意义的方式嵌套过程。一般来说,这会使单独的编译变得相当复杂。这不同于没有嵌套过程(函数等)的 C-like 语言,因为它们可以引用的唯一 non-local 标识符是文件范围或全局范围(如果我的这些术语正确的话)。
这里,变量 x
和 y
是某些过程的局部变量,因此在堆栈上。只是为了让它更复杂,q
是递归的,这使得 "distance down the stack" 从它的最内层调用到 x
和 y
的位置是一个可变的数量,所以它不仅仅是从一些 stack-frame 指针编译一个固定值的问题。
然而,有些系统允许单独编译。据我所知,有一些限制,例如编译单元(一个文件,如果你愿意的话)必须只包含过程 'at the top level'。他们可能还需要一些扩展语法(如 'external procedure foo')来告诉编译器所引用的内容不应在当前文件中定义。