下乡扫盲C语言 Chapter 0

    最近在看windows相关的一些书,不禁感慨,之前学习过程中经历的很多困难实质上是缺乏一些基础知识,而且在国内互联网论坛上少有关于这类基础知识的讨论和讲解。即使有,也大多从老旧的帖子中抄袭而成,多有错误和过时的地方。因此我决心写一个成系统的扫盲文章。第一个短期的计划是关于C语言的。我假设我的大部分读者应该是正在上,或者刚刚修过"高级语言程序设计(C语言)"这门课程的大一,大二学生。我希望先简单解释一些基础概念,常见的名词。然后会用几篇文章讲解编写C语言程序的几种工具,我会把重点放在微软的Visual Studio 2017,完全跳过VC6.0。再之后会有一两篇文章解释常见的编译期错误和运行时错误,讲解如何查错,如何调试一个程序。最后可能有几篇面向希望能进一步提高自己水平的读者的文章。大体就是这样了。

 

    0.什么是C语言

         C语言是一种高级程序语言,所谓高级程序语言,"In computer science,a high-level programming language is a programming language with strong abstraction from the details of the computer"一种高级语言是抽象的,不涉及计算机硬件细节的语言。这就使得高级语言有两个特点,一是通过抽象减少了程序员需要思考的范围,二是通过改变在不同平台上的实现,使得编写的程序可以不加修改地在不同的平台上运行。

         我们更关心第二个特点,这表示,同样的一个helloworld程序,无论在linux还是windows系统,在amd或intel的CPU上运行,都应该在屏幕上打印一个"hello world"。在C语言刚出生时,这其实已经是一个惊人的进步,在那之前,程序员们使用汇编语言写程序,然而汇编语言完全依赖于你使用的机器,也就是说,你在一台机器上运行的程序,几乎不可能在另外一台使用了不同的硬件的电脑上运行。

        

         疲于奔命的程序员说,要有高级语言,就有了C语言。

                                ------- Genesis 1:3

    1.C语言其实有好几种

         这里我们来讲一点历史。

         在20世纪70年代末,Dennis MacAlistair Ritchie与Kenneth Lane Thompson在贝尔实验室设计,开发了C语言。然而后来的几年里,很多公司和个人开发者都不是直接使用最开始的这一版本,而是各自为方便使用而对C语言进行了修改。

         1989年,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言订定了一套完整的国际标准语法,称为ANSI C(又称 C89),作为C语言的标准。二十世纪八十年代至今的各种程序开发工具(编译器,调试器,文本编辑器等)一般都支持 ANSI C。这是被广泛接受的一个版本,国内大部分教科书和老师的教学都基于ANSI C。      

         C语言还有不同的版本,但比较重要的只有三个。

         ANSI C (C89) 这是被最广泛接受的一个

         C99  这个版本支持了很多新的语法,很多编译器也实现了这个标准(例如GCC),大部分情况下使用C99新增的特性是没问题的

         C11  这个版本。。。实际上还没有编译器完全实现,鉴于笔者寿命有限,不再提及。

        

       2.hello world,  hello assembly, hello CST

  我想读者们已经运行过一个hello world程序,大概像这样

  

#include<stdio.h>
int main()
{
    printf("hello world\n");
    return 0;
}

 

  你可能已经单步调试过这个程序,在第三行打一个断点,然后一行行执行,直到第五行,程序结束。

  但是,你的程序其实并不是你看到的这么简单,它实际上长这样。(源代码的部分标为黑体)

 1 #include<stdio.h>
 2 int main()
 3 {
 4 00007FF6B7BA0590  push        rbp  
 5 00007FF6B7BA0592  push        rdi  
 6 00007FF6B7BA0593  sub         rsp,0E8h  
 7 00007FF6B7BA059A  lea         rbp,[rsp+20h]  
 8 00007FF6B7BA059F  mov         rdi,rsp  
 9 00007FF6B7BA05A2  mov         ecx,3Ah  
10 00007FF6B7BA05A7  mov         eax,0CCCCCCCCh  
11 00007FF6B7BA05AC  rep stos    dword ptr [rdi]  
12     printf("hello world\n");
13 00007FF6B7BA05AE  lea         rcx,[string "hello world\n" (07FF6B7BB03E8h)]  
14 00007FF6B7BA05B5  call        printf (07FF6B7B91528h)  
15     return 0;
16 00007FF6B7BA05BA  xor         eax,eax  
17 }
18 00007FF6B7BA05BC  lea         rsp,[rbp+0C8h]  
19 00007FF6B7BA05C3  pop         rdi  
20 00007FF6B7BA05C4  pop         rbp  
21 00007FF6B7BA05C5  ret

   怎么样,是不是仿佛看到了克苏鲁一样,san值狂降?

   这其实是helloworld在VS2017中,经编译产生的汇编代码。

  这段代码做了三件事,

  一,保存程序上下文(context)

  二,调用printf函数(14行)

  三,恢复程序上下文(contxet)

 

  有些比较聪明的读者可能已经立刻明白过来,举手回答说,代码的编译就是把代码转换成汇编代码,汇编代码可以轻易地转换成机器代码,直接运行。这种想法已经相当接近实际情况,但如果只是单纯翻译源代码,4-10行和18-21行的程序又是从哪儿来的呢?这段代码其实是编译器悄悄塞进来的,没有这些额外的工作,程序是无法正确运行的,涉及到的知识点太多,本文中不再深入了。但在接下来的第一章,我将解释编译器对你的代码做了什么,ide和编译器有何不同。

  但更重要的是,这个printf函数是打哪来的呢?我们都知道在C语言里,函数要先声明,并在某处定义出来,才能调用。

  输入输出的printf,scanf一族(还有sscanf,sprintf.....)被定义在stdio.h(standard input/output)中,

  关注数学运算的pow(),sqrt(),fabs()被定义在math.h中

  关于时间的time()等函数,tm等结构体被定义在time.h中

  这些头文件属于C语言标准,包含了具体实现的文件被称作C语言标准库(C Standard Library)

  在之后的第二章,将注重于说明,lib,dll,exe等文件的关系,说明C语言标准库在我们的程序中起什么作用。

 

  这只是一篇开坑的说明,所以先到此为止了。

  亲爱的读者朋友们,明年再见,啊不,下周再见。

 

  

转载于:https://www.cnblogs.com/TCR0/p/8732652.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值