LCC-win32与C编程简介(2)

        本教程假定你的系统已经安装了Lcc-win32.学习本教程你将需要用到此编译程序,且Lcc-win32是免费的,你可以在学习本教程前到http://www.q-softwaresolutions.com下载并安装Lcc-win32.
    本教程不是一个完整的C语言教程,如果你从未学习过C语言编程,建议你先借助其它参考书(可参考本教程末尾列出的书本)学习C语言编程. 尽管在这里将从基础开始介绍,但并没有包含C语言的全部功能与特性.需要提出,这不是一个用以学习C语言编程的文档或参考书.在这里C标准库将给予介绍, 但并不详尽[1].

       在开始之前,先回答这样一个问题:为什么要学C?
       在C的出现时曾被广泛地批评,很多人迅速提出它的问题和缺点.但随着编程语言的更替,C屹立不倒.
Lcc-win32已发行了多年,有很多人,包括Dennis Ritchie,C语言的创作者[2],对这个问题的回答很简单:
如你想让你的软件可以长时间的得到应用,不要学"今天的编程语言",学C.

      C没有特别的亮点打动你,它不是一种面向对象程序设计语言,但如果你希望,你可以用C进行对象程序设计[3].它不是一种功能性语言(functional language),但如果你喜欢,你可以用C进行功能性编程(functional programming)[4].很多LISP解释程序和Scheme解释程序/编译程序是用C写的.你可以用C进行表单处理(list processing),当然不会像用LISP那样方便,但你可以在C做到.它有很多诸如递归等精华编程的功能,所有的这些功能在这里将给予介绍.
 很多人认为C缺乏Java的简易和C++模板及其它特别吸引人的东西的复杂.诚然,C是一种简单的语言,
没有任何装饰.但正是这些特性的缺乏使得C适合作为一种首先介绍的综合的高级语言,允许你很好的
控制你的程序的运行而没有任何隐藏的东西.当你没有告诉编译程序怎样做时,编译程序将什么也不做.
尽管在你将用到的C编译程序将Java的一些特性如回收站(the garbage collection)被整合到C的执行中,
但C语言是仍是透明的[5].正如各种语言的更替,C屹立不倒.在70年代它作为UNIX操作系统发展的核心[[6],
80年代作为微型计算机(microcomputer)的更新的核心,而像C++,Delphi,Java及其它编程语言来了又去,但C依然保留自我本性.

1.1 C程序设计的结构
  一个C语言程序由一个或多个称之为源模块的文本文件组成.每个这样的模块则由若干函数组成,即:
一小块的代码完成一些任务[7],和数据,即:变量或表在程序的开始被初始化.有一个名为main的特殊的函数
作为程序执行的开始[[8].在C里面,文件里代码的结构是有语义的.主要的源码定义一个编译单位作为
参数传递给编译程序(compiler)[[9].
  一个编译单位可以使用#include预处理指令输入通用的定义,或使用extern标识符来声明之[[10].
  C支持独立的编辑模块,即:你可以将你的程序分为几个独立的模块并分别对它们进行编译,然后再用连接程序将它们连接为最终程序.通常每个模块分别用不同的包含各种函数或数据声明的文本文件编写.模块之间的接口在一个用以描述程序的类型或函数对一些模块的可见性的“头文件”里.这些文件有一个“.h”的扩展名,它们分为两类,一种是系统的,由Lcc-win32提供,另一种是私的,由用户自已建立.
  一个函数由一个参数表, 函数体,及一个可选的返回值组成[[11].函数体可以包含局部变量的声明,即:变量在程序执行到函数体时被激活.
函数体为一系列由分号隔开的表达式的集合.每一个语句可以是一个算法操作,一个赋值,一个函数调用,或是一个复合的语句,即:一个语句包含其它语句.

1.2 Hello
  我们将使用由C语言作者[12]给出的一个著名的例子来向读者介绍C的风味.我们编写一个在屏幕上打印出信息“Hello”的程序.

#include (1)
int main(void) (2)
{ (3)
printf("Hello\n"); (4)
return 0; (5)
} (6)
  1) 使用一个称之为‘预处理’的编译程序功能,你可以用“#include”指令原文地包含整个C源文件.在这里我们包含一个编译程序标准库里的“stdio.h”头文件[13].
  2) 我们定义了一个名为“main”的返回一个整数的函数,且不接收参数(void).[14]
  3) 函数体由两个花括号( “{” 和 “}” )包含起来的语句构成.
  4) 我们调用一个标准函数“printf”里面的格式控制字符串参数将被显示在屏幕上.在C里,一个函数调用是这样的: 函数名 ‘(‘argument-list ‘)’.在这里所调用的函数的名为“printf”,其参数列表为一字符串“Hello\n”[15].字符串用一双引号括起来.它们在C里作为一个字符串数组并以一个0字节结束.
  5) 函数运行结束后返回到调用函数的语句,可选的,它可以返回一个结果,这里返回一个整数0.
  6) 函数体结束花括号.
  C语言程序使用文本文件保存,通常使用.c作为文件的扩展名.你可以在任何你想使用的文本文件编辑器编辑这些文件,在Lcc-win32里作一个名为“Wedit”的特殊编辑器编写程序.此程序可以方便地进入程序文本里,并以C程序的风格显示程序文本.
  现在编写此程序,我们启动Wedit并输入上面程序[16].


当你完成程序代码的输入,你便可以使用compiler菜单或按F9编译并连接程序[17].
  要运行此程序,你可以使用compiler菜单上的“execute”选项(Ctrl+F5),或打开一个命令行窗口键入程序的名.让我们先做一次.
  首先,我们需要知道的是我们想要运行的程序的名.这个容易:我们使用Wedit utils菜单中的executable stats选项.我们看到以下显示.


我们看窗口下方面板的第一行,程序的执行调用:
  h:\lcc\projects\hello.exe.[18]
  我们可以打开命令行窗口,并键入:
  C:\>h:\lcc\projects\lcc1\hello.exe
  Hello
  C:\>
  上面显示了程序运行的结果.
  但我们如何知道显示一个字符串调用“printf” 函数呢?
  因为库的说明文档告诉我们的…一个刚开始使用C的用户要做的第一件事便是浏览系统所提供的库函数,他/她就可以方便的调用常用的函数而不必浪费太多的时间去重新编写这些基本的函数.库中有千千万万个为各种任务编写的各种类型的函数, printf便是这些函数中的一个.我们将在下面的内容讨论它们.

1.2.1 编译过程的概述
  当你在编辑器里按下F9生成一个可执行文件时,将执行一系列复杂的处理,但所有的这些对于你是不可见的.下面将对这些做一个概述,让你至少可以了解在后台发生了什么.Wedit将调用C编译程序.这个程序在Lcc的安装目录里名为:lcc.exe.如:你将Lcc安装在c:\lcc,则 lcc.exe将放在c:\lcc\bin.
  编译程序将读入你的源文件,并产生另一个称为目标文件的文件,[19]其名字与你的源文件的名字相同,只是扩展名为.obj.C支持分开独立编辑模块,即:你可以将你的多个模块源文件分别产生多个目标文件,然后用连接程序lcclnk.exe连接产生可执行文件.
  Lcclnk.exe是一个连接程序.它将读入不同的目标文件,库文件或其它文件,并产生一个可执行文件或一个动态连接库(dynamically loaded library):一个DLL文件.
  当编译你的hello.c文件时,编译程序产生一个“hello.obj”文件,再由连接程序以“hello.obj”文件产生 hello.exe可执行文件.连接程序将使用在\lcc\lib目录下多个文件以产生可执行文件并将之与系统的DLLs绑定,如几乎所有程序都用到的 kernel32.dll, crtdll.dll,及其它.
  Lcc编译程序的工作的描述的细节可在技术文档里找到,这里只给予介绍其主要步骤:
  源文件被第一次预处理.#include指令被执行,包含文件里的代码被加入到源文件里.[20]
  编译程序将已经过预处理的文本产生一系列中间指令代码.[21]再由代码生成程序生成汇编程序代码.[22]
  最后编译程序生成一个扩展名为.obj的文件.这个文件经过连接程序lcclin的连接产生可执行文件.
  组织并输入这些命令是让人厌烦的为此,当你按下F9功能键时IDE(Integrated Development Environment,集成开发环境)将自动为你完成全部操作.

1.2.2 术语
  在上面Wedit窗口里出现的术语解释如下:
  1 Size of code.这个数字表示你的程序指令将要使用的字节数.包程序启动,相关函数代码连接生成的指令,如:printf,等等.
  2 Size of initialized data:这个数字表示表,常量等其它初始数据使用的字节数.在这个例子可以看到包括字符串“hello”及其它从C库里面加进去的一些常量.
  3 Uninitialized data:这表示你的程序为变量保留的空间的大小.在程序启动时将由系统赋于值0.
  4 Size of image:这表示程序加载时所用的全部内存空间,包括上面所提及的.因为对列的原因这个数字大于上述各值的代数和.

 

[1] 可以到"How to find more information"查看Lcc-win32的文档资料.
[2] Dennis Ritchie编写了Lcc-win32的预处理程序
[3] 对象C产生C,像Eiffel和其它的一些面向对象语言.C,正好因为这种程序模块的缺乏被适用于他们的表达. 甚至C++也是作为C编译程序的预处理程序开始的.
[4] 查看“Illinois FP”语言在C的执行,很多其它的功能性编程语言是用C编写的.
[5] Lisp和scheme,这两种面向表单语言早在几十年前已经使用自动回收站.APL和其它解释程序也提供这种功能.同样Lcc-win32提供由Hans Boehm编写的垃圾回收器.
[6] 今天,Linux的核心完全是由C编写的.
[7] 函数和过程在C里没有差别.一个过程是一个没有返回值的函数.
[8] 实际上,程序开始的代码是main函数,当main函数返回时,程序即随之结束.更多细节请参考技术文件.
[9] 任何一种程序的开始,在任何一种计算机的语言里,有两种主要的内存类型:程序的代码(code)段,即:程序将执行的机器指令序列.这个段有一个“入口” (“entry point”).上面提及的在C里面的“main”过程,或其它过程是作为入口使用的.程序的静态数据(data)段,即:程序一开始就确定的字符串,数字或表.这些数据可以被更进一步分为一个初始数据段,或仅仅是空的,当程序加载时这些保留的空间被操作系统初始化为0.
[10] 你不能选择性的从其它的包含文件输入一些标识符.你只能选择输入全部或不输入.
[11] 在C只有一个返回值.一个函数,然而可以通过修改它的环境来返回多个值.
[12] 这是一个经典的例子,出自1974年B. W.Kernighan的C语言教程,这是在“The C programming Language”出版的4年之前.他们的例子到今天仍为人们所用,虽然编译时会带来一些警告:
  main() { printf(“Hello world\n”); }
[13] 头文件的名字用一对 < > 括起来,表示告诉编译程序从标准包含目录里面查找该头文件,而不是在当前目录.如果你想从当前目录或其它目录里查找头文件,可以使用双引号将头文件名括起来,像: #include “myfile.h”.
[14] 这是两种用以定义“main”函数的方法之一.下面我们将看到另一种.
[15] 字符串可以包含一般字符,也可以使用制表符如转行(\n)跳格符(\t),或其它.详细请参考其它参考书.
[16] 你可以双击Wedit的图标或在WINDOWS开始菜单的运行里输入全路径运行Wedit,如:若你将Lcc-win32安装在c:\lcc则Wedit将会在c:\lcc\bin\wedit.exe.
[17] 如果如此不运行或收到警告,你可能在安装过程中出现问题(除非你键入错误).或程序有Bug.紧记若你用EMAIL告诉我程序的Bug,我将要解决安装程序的错误,所以详尽将你遇到的问题告诉我将对于我解决问题十分重要.当你单击compiler 按钮Wedit会为你生成一个默认的工程.如果磁盘没有足够的空间时编译将出错,或安装时出错,Wedit找不到编译程序,又或其它原因.若当你见到错误信息时请勿惊慌,并尽量根据信息修正错误.一个通常的错误是当你往一个不足空间安装一个旧版本的Wedit时,尽管会有醒目的警告提示你不应继续时,大多数人习惯不读警告而继续安装,这将导致Lcc-win32 无法工作.然后你便抱怨起我我.我已经在新的版本将之修正.但仍会有错误发生.
[18] 下面几行输出的含义将在下文介绍.
[19] 当然这与面向对象程序设计毫无关系!
[20] 当你调用编译程序时使用-E开关可以见到处理的过程.如你在命令行窗口中键入:lcc –E hello.c你可以见到预处理的全过程.生成的结果文件是:hello.i.
[21] 同样,你可以通过lcc –Z hello.c见到生成的中间指令代码.其中间指令代码文件名这hello.lil.
[22] 汇编程序代码可以通过lcc –S hello.c命令生成.汇编程序代码文件名为:hwllo.asm.生成的文件包含C程序代码的列表及其对应的汇编程序代码.

作者:Vitamin C   更新日期:2004-12-23
来源:c-sea.net   浏览次数:

相关文章

相关评论   发表评论