加深代码理解系列…..
Welcome to the wild no heroes and villains.
高级计算机语言和编译器
C语言本身是高级语言,所谓高级编程语言,就是一种独立于机器,面向过程(POP)或是面向对象(OOP)的编程语言、
C语言就是一门面向过程
的编程语言。
使用高级语言可以在更抽象的层面表达程序员的想法而不必要考虑CPU在完成任务时具体需要哪些步骤。(叒又是抽象,所以具象是否是表示接近一项事物的本质呢?)
计算机自己并不理解高级语言其高级指令,在这里编译器派上了用场,它将高级语言程序翻译成计算机可以理解的机器语言指令集程序。
在学习C语言之前,有必要了解一下其编程机制。
C的编程机制
C是可移植性语言,所以可以在多种环境中运行使用,包括UNIX,Linux,MS-DOS,Windows,Mac OS
常说C\C++是跨平台语言,其原理是使用平台相关的编译器生成对应平台的可执行文件
,如在Windows中.c.cpp文件将被编译成PE格式
,而在Linux系统中将会被编译成ELF格式
以上提到的也许只是部分环境,但终究他们有一些共有的方面。
C的代码被储存在文本文件中,该文件被称为“源代码文件 - Source code file”
通常由 basename
基本名 + .c (extension)
扩展名构成
C通过编译和链接将源代码文件转换为可执行文件。编译器将源代码转换成中间代码(通常为机器语言代码),链接器把中间代码与其他代码进行合并(合并代码)
,最后再与库文件
和系统的标准启动代码
合并生成可执行文件。
Data Types
上溢(overflow)
计算导致的数字过大,超过当前类型所能表达的范围时,就发生了上溢,现代C语言发生这种情况会给上溢的数据赋值一个表示无穷大
的特定值。
使用数据类型时,若是将一个值初始化给不同类型的变量时,编译器会自动转换成变量匹配的类型
,这可能会导致部分数据丢失。 比如将一个double 值赋给 float 变量,由于C语言只会保留float的前六位精度,其他位的数据将被丢弃。
Refresh Output
关于printf
何时将语句输出到终端,起初printf 会将语句发送到缓冲区
(buffer )【作为中间储存区域】 中,由于C标准的明确规定, printf 在遇到 换行符、 缓存区满时会将内容输出到屏幕,这一过程为刷新缓存区。 如果没有换行符且缓存区也没有满,但是下一条语句为 scanf()
语句时,scanf要求用户输入,此时 printf 将被迫将缓存区内容输出
Pointer & Multiple Array - 指针与多维数组
指针是一个值为内存地址的变量(或数据对象)
*(星号) , 即间接运算符(indirection operator)
, 即间接获取指针指向地址处的数据
其也称为 解引用运算符(dereferencing operator
)
e.g.
1 | char *pt; |
Declaration of Pointer 指针声明
指针的声明需要指定指针所指向的变量的类型
,不同的数据类型占据不同的内存空间
通常在声明的时候有空格, 间接运算符和指针名之间的空格可有可无(一般省略)
1 | int (*arr)[4]; |
REFER TO PAGE 304
为什么要使用圆括号? 因为[]
的优先级高于*
如果此处不使用圆括号, 则 int *arr[4]
表示 arr is a array point to pointer
即 arr[4] 为一个数组, *表示arr数组中含有4个指针,int 表示每个指针指向的类型为int
注意使用数组法声明多维数组时,第二个方括号中的数据不能为空. 否则编译器无法知道.
数组名(第一个元素的地址) + 1 需要加上多少字节才能到第二个元素的地址
如
1 | int sum(int ar[][4],int rows); |
如果是空的编译器就不知道如何处理 如何得到后续地址
size_t = long unsigned int 64位系统中 size_t = long long unsigned int
声明指向多维数组的指针时 只能省略第一个方括号中的值, 第一对方括号用于表示这是一个指针…
Variable Length Array - 变长数组
C的数组维数 必须是常量 , 不能使用变量来代替
为了创建能处理任意大小的二维数组的函数 C99中添加了变长数组 , 允许使用变量表示数组的维度
‘变’指的是在创建数组的时候可以使用变量表示数组维度
, 而非可以改变数组的大小
注意如果作为VLA变长数组的维度的参数(变量) 必须于VLA之前声明.
函数原型中的VLA参数名可以省略,但必须使用 星号
代替
Function Types - 函数类型
函数类型指的是函数的返回值类型
,而非函数的参数类型
且不要搞混函数的声明 declaration
和定义 definition
, 函数声明是告知编译器函数的类型, 定义则是提供实际的代码
⚔ Exercises - Pick ur weapon and face it.
实践是理论的基础,是理论的出发点和归宿点,对理论起决定作用,理论必须与实践紧密结合,理论必须接受实践的检验,为实践服务,随着实践的发展而发展。
咳咳…就是些小练习…..
Fibonacci Sequence
1 |
|
Quick sort
1 |
|