类型,运算符与表达式
类型,运算符与表达式1.变量名
变量名以下划线“_”和字母开头,是由字母和数数字组成的序列,下划线被当成字母。
变量不能使用保留的关键字“if,else,int等。
选择的变量名要能尽量表达变量的用途。
2.数据类型及长度
C语言只提供4种基本数据类型
char 字符型,占用__一个字节__。
int 整型,通常反映了__所用机器中整数的最自然长度__。
float 单精度浮点型。
double 双精度浮点型。
__short__与__long__两个限定符用于限定整型(int)。
(声明中关键字_int_可以省略)
long 类型通常为32位,short类型通常为16位,int类型可以为16位或32位。(根据各个硬件特性不同,长度也不同,但至少int类型长度不得大于long,不得小于short。
类型限定符__signed__和__unsigned__可用于限定char类型或任何整型。
unsigned类型的数总是正值或零,并遵守[^算术模二]定律,不带限定符的char类型对象是否带符号则取决于具体机器,但可打印字符总是正值。
long duoble 类型表 ...
第二章:编译和链接_3_4
第二章:编译和链接_3_42.3 链接器的年龄比编译器长
程序并不是一写好久永远不变的,它会经常被修改。比如我们在第一条指令之后,第五条指令之前插入了一条或多条指令,那么第五条指令后面的的指令的位置也会相应的往后移动,当程序修改的时候,这些位置都要重新计算,十分繁琐又耗时,并且容易出错。这种重新计算各个目标地址的过程叫做 重定位
于是 符号这个概念随着汇编语言的普及迅速的被使用,他可以用来表示一个地址,这个地址可能是一段程序的起始地址,也可以是一个变量的起始地址。
2.4 模块拼装——静态链接程序设计模块化是人们一直在追求的目标,因为当一个系统十分复杂的时候,我们不得不将一个复杂的系统逐步分割成小的系统以达到各个突破的目的。
一个复杂的软件也是如此,人们把每个源代码模块独立的编译,然后按照须要将他们”组装”起来,这个组装模块的过程就是 链接。链接的主要内容就是把各个模块之间相互引用的部分都处理好,使得各个模块能够正确地衔接。
链接的过程主要包括了 地址和空间分配,符号决议,和重定位等这些步骤。
最基本的静态链接就是将源代码经过编译器编译成 目标文件,目标文件和 库(Library)一 ...
第二章:编译和链接_2
第二章:编译和链接_2编译器做了什么从直观来说,编译器就是将高级语言翻译成机器语言的一个工具。编译器的存在可以让程序员更加关注程序本身的逻辑,而尽量少考虑计算机本身的限制,如字长,内存大小,通信方式,存储方式。
编译过程一般可以分为6步, 扫描,语法分析,语义分析,源代码优化,代码生成和目标代码优化
2.2.1 词法分析首先源代码被输入到 扫描器,扫描器的任务很简单,它只是简单地进行词法分析,运用一种类似于 有限状态机的算法可以很轻松地将源代码的字符序列分割成一系列的 记号(token)。
词法分析产生的记号一般可以分为以下几类: 关键字,标识符,字面量(包含数字,字符串)和特殊符号(如加号,等号)。
在识别记号的同时,扫描器也完成了其他的工作。比如将标识符放到符号表,将数字,字符串常量存放到文字表中,以备后面的步骤使用。
有一个叫 lex的程序可以实现词法扫描。
2.2.2 语法分析接下来 语法分析器将对由扫描器产生的记号进行语法分析,从而产生 语法树。整个过程采用了 上下文无关语法的分析手段,语法分析器产生的语法树就是以表达式为结点的树。
正如前面的词法分析有lex一样,语法分析有 ...
第二章:编译和链接_1
第二章:编译和链接_12.1 被隐藏了的过程
当我们用GCC编译文件的时候有很多步骤被隐藏了,GCC编译的过程可以分为四个步骤,分别是 预处理,编译,汇编,链接
2.1.1 预编译使用命令来让编译器只执行预编译
123$gcc -E hello.c -o hello.i或者$gcc hello.c > hello.i
预编译的主要过程是处理那些源代码中的以“#”开头的预编译指令。比如“#include”,“#define”等,主要处理规则如下:
将所有的“#define”删除,并且展开所有的宏定义。
处理所有条件预编译指令,比如“#if”,“#ifdef”,“#elif’,”#else”,”#endif”
处理“#include”预编译指令,将被包含的文件插入到该预编译的位置。这个过程是递归的,也就是说被包含的文件还可能包含其他文件。
删除所有的注释“//”和”/**/“。
添加行号和文件名标识,比如#2 “hello.c” 2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号。
保留所有的#pra ...
第一章:计算机的软硬件基本结构—Q&A
第一章:计算机的软硬件基本结构—Q&A1.1 从hello World说起问题
程序为什么要被编译了以后才可以运行?
A:
编程语言是程序员的语言,但是不是计算机能够理解的语言,计算机能够理解的语言只有机器码,也就是二进制的0和1。所以程序需要被编译才能运行。
编译器在把C语言程序转换为可以执行的机器码的过程中做了什么,怎么做的?
A:
编译分为四个步骤,分别是预处理,编译,汇编,链接。预处理首先对以#开头的预编译命令处理。删除所有注释。编译会经过一系列的词法分析,语法分析,语义分析,优化后产生相应的汇编代码文件。汇编负责将汇编文件转换为机器可以执行的指令。链接负责将我们程序里引用的库函数和我们写的程序进行链接。
最后编译出来的可执行文件里面是是什么?除了机器码还有什么?他们怎么存放的,怎么组织?
A:
这个问题不太会,等学完后来填坑。
#include<stdio.h>是什么意思?将stdio.h包含进来意味着什么?C语言库又是什么?它怎么实现的?
A:
#include<stdio.h>是将stdio.h这个库函数给引入进来。include的效 ...
第一章:计算机的软硬件基本结构_6
第一章:计算机的软硬件基本结构—61.6 众人拾柴火焰高1.6.1 线程基础
在现代软件系统中,线程和进程一样重要。特别是随着CPU频率增长开始出现停滞,而开始向多核发展。多线程,作为实现软件并发执行的一个重要的方法,也开始具有越来越重要的地位。
什么是线程 线程(Thread),有时候被称为 轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元,一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。
通常意义上,一个进程由一个到多个线程组成,各个线程间共享程序的内存空间(包括代码段,数据段,堆等)以及一些进程级的资源(打开文件和信号)
大多数软件应用中,线程数量都不只一个。多个线程可以互不干扰地并发执行,并共享进程的全局变量和堆的数据。和单线程对比,多线程具有的优势为:
某个操作可能会陷入长时间的等待,等待的线程会进入睡眠状态,无法继续执行,多线程可以有效利用等待的时间。
某个操作会消耗大量的时间(通常是计算),如果只有一个线程,程序和用户之间的交互会中断。多线程可以让一个线程负责交互,另一个线程负责计算。
程序逻辑本身就需要并发 ...
第一章:计算机的软硬件基本结构_5
第一章:计算机的软硬件基本结构_51.5 内存不够怎么办
操作系统的多任务功能使得CPU能够在多个进程之间很好的共享,从进程角度好像它独占了CPU而不用考虑与其他进程分享CPU。
为了更有效的利用硬件资源,我们必须同时运行多个程序,正如前面的多道程序,分时系统和多任务一样,当我们能够同时运行多个程序时,CPU的利用率较高。但是就会有一个很明显的问题, 如何将计算机上有限的物理内存分配给多个程序使用。
在分配内存时会出现的问题。
地址空间不隔离 所有程序直接访问物理地址,程序所使用的内存空间不是相互隔离的。恶意的程序可以很容易改写其他程序的内存数据,以到达破坏的目的。
内存使用效率低 由于没有有效的内存管理机制,通常我们正在运行程序A的时候要是想运行程序B,但是这个时候内存空间其实已经不够用了,于是计算机便会将程序A换出到磁盘或者更多来释放足够的空间来运行程序B。中间有大量的数据在换入换出,导致效率低下。
程序运行的地址不确定 因为程序每次需要装入运行时,我们需要给他从内存中分配一块足够大的空闲区域。这个区域的位置是不确定的。这给程序的编写造成了一定的麻烦,因为 ...
第一章:计算机的软硬件基本结构_4
第一章:计算机的软硬件基本结构_41.4 操作系统做什么
操作系统的一个功能是提供抽象的接口,另一个主要功能是管理硬件资源。
1.4.1 不要让CPU打盹在计算机发展的早期,CPU资源十分昂贵,当CPU运行一个程序的时候,该程序需要读写磁盘,CPU就空闲下来了。这极大的浪费了CPU的资源。于是人们编写了一个监控程序,当某个程序暂时无须使用CPU时,监控程序就把另外正在等待CPU资源的程序启动,使得CPU能充分利用起来。这被称为 多道程序。但是这种程序的调度策略太过粗糙。程序之间不分轻重缓急。
稍微改进了一下,程序运行模式就变成了一种协作的模式。每个程序运行一段时间以后都主动让出CPu给其他程序,使得一段时间内每个程序都有机会运行一小段时间。这种程序协作模式叫做 分时系统。但是这种方式如果有一个非常耗时的计算在运行,那就会一直霸占着计算机。
于是出现了更先进的操作系统模式,这便是我们熟悉的 多任务系统,操作系统接管了所有硬件资源,并且本身运行在一个受硬件保护的级别。所有应用程序都以 进程的方式运行在比操作系统权限更低的级别。每个进程都有自己独立的地址空间,使得进程之间的地址空间相互隔离 ...
第一章:计算机的软硬件基本结构_3
第一章:计算机的软硬件基本结构_31.3 站得高,望得远系统软件可以分为两块,一块是平台性的,比如操作系统内核,驱动程序,运行库,和数以千计的系统工具。另一块是用于程序开发的,比如编译器,汇编器,链接器等开发工具和开发库。
计算机系统软件体系结构采用一种层的结构,有人说过一句名言:
计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决!
系统软件体系结构中,各种软件的位置如下图所示。
每个层次之间相互通过共同的通信协议来通信,我们一般将其称为 接口,接口下面那层是接口的提供者,由他定义接口;接口上面那层是借接口的使用者,它使用该接口来实现所需要的功能。
我们的软件体系中,位于最上层的应用程序,比如我们平时用到的网络浏览器,多媒体播放器,图片浏览器等。从整天层次来看,开发工具和应用程序是属于一个同一个层次的,因为他们都使用一个接口,那就是操作系统 应用程序编程接口(API)应用程序接口的提供者是运行库。
运行库使用操作系统提供的系统调用接口,系统调用接口在实现中往往以 软件中断的方式提供,比如Linux使用的0x80号中断作为系统调用接口,Windos使用0x2E号中断作为 ...
第一章:计算机的软硬件基本结构_2
第一章:计算机的软硬件基本结构1.2 万变不离其宗
计算机是个非常广泛的概念,包括大到要装数层楼的超级计算机,也有小到手上拿的手机上的嵌入式芯片都可以被称为计算机。
撇开计算机硬件中复杂的各种设备,芯片,以及外围接口的等,站在软件开发者的角度去看,我们只需要抓住硬件的几个关键部件,对于系统应用开发者来说,最为关键的部件分别是,中央处理器CPU,内存和I/O控制芯片,对于普通应用程序开发者来说,他们只需要关心CPU以外其他的都不需要,对于一些高级平台的开发者来说(如java,.NET或脚本语言开发者),连 CPU都不需要关心。因为平台为他们提供了一个通用的抽象的计算机,他们只需要关心这个抽象的计算机就可以了。
早期的计算机没有复杂的图形功能,只需要一个 总线(BUS)来连接CPU,内存和I/O设备。
后来由于CPU核心频率的提升,导致内存跟不上CPU的速度,于是产生了与内存频率一致的 系统总线,而CPU采用倍频的方式与系统总线进行通信。后面随着3D游戏和多媒体的发展,使得图形芯片需要跟CPU和内存之间大量交换数据,为了协调CPU,内存和高速的图形设备,人们专门设计 ...