函数
简介
函数是一段可以重复执行的代码。它可以接受不同的参数,完成对应的操作。下面的例子就是一个函数。
123int plus_one(int n) { return n + 1;}
上面的代码声明了一个函数plus_one()。
函数声明的语法有以下几点,需要注意。
(1)返回值类型。函数声明时,首先需要给出返回值的类型,上例是int,表示函数plus_one()返回一个整数。
(2)参数。函数名后面的圆括号里面,需要声明参数的类型和参数名,plus_one(int n)表示这个函数有一个整数参数n。
(3)函数体。函数体要写在大括号里面,后面(即大括号外面)不需要加分号。大括号的起始位置,可以跟函数名在同一行,也可以另起一行,本书采用同一行的写法。
(4)return语句。return语句给出函数的返回值,程序运行到这一行,就会跳出函数体,结束函数的调用。如果函数没有返回值,可以省略return语句,或者写成return;。
调用函数时,只要在函数名后面加上圆括号就可以了,实际的参数放在圆括号里面,就像下面这样。
12int a = plus_one(13 ...
指针
指针是 C 语言最重要的概念之一,也是最难理解的概念之一。
简介
指针是什么?首先,它是一个值,这个值代表一个内存地址,因此指针相当于指向某个内存地址的路标。
字符*表示指针,通常跟在类型关键字的后面,表示指针指向的是什么类型的值。比如,char*表示一个指向字符的指针,float*表示一个指向float类型的值的指针。
1int* intPtr;
上面示例声明了一个变量intPtr,它是一个指针,指向的内存地址存放的是一个整数。
星号*可以放在变量名与类型关键字之间的任何地方,下面的写法都是有效的。
123int *intPtr;int * intPtr;int* intPtr;
本书使用星号紧跟在类型关键字后面的写法(即int* intPtr;),因为这样可以体现,指针变量就是一个普通变量,只不过它的值是内存地址而已。
这种写法有一个地方需要注意,如果同一行声明两个指针变量,那么需要写成下面这样。
12345// 正确int * foo, * bar;// 错误int* foo, bar;
上面示例中,第二行的执行结果是,foo是整数指针变量,而bar是整数变量, ...
数据类型
C
语言的每一种数据,都是有类型(type)的,编译器必须知道数据的类型,才能操作数据。所谓“类型”,就是相似的数据所拥有的共同特征,那么一旦知道某个值的数据类型,就能知道该值的特征和操作方式。
基本数据类型有三种:字符(char)、整数(int)和浮点数(float)。复杂的类型都是基于它们构建的。
字符类型
字符类型指的是单个字符,类型声明使用char关键字。
1char c = 'B';
上面示例声明了变量c是字符类型,并将其赋值为字母B。
C 语言规定,字符常量必须放在单引号里面。
在计算机内部,字符类型使用一个字节(8位)存储。C
语言将其当作整数处理,所以字符类型就是宽度为一个字节的整数。每个字符对应一个整数(由
ASCII 码确定),比如B对应整数66。
字符类型在不同计算机的默认范围是不一样的。一些系统默认为-128到127,另一些系统默认为0到255。这两种范围正好都能覆盖0到127的
ASCII 字符范围。
只要在字符类型的范围之内,整数与字符是可以互换的,都可以赋值给字符类型的变量。
123char c = 66;// 等同于cha ...
流程控制
C
语言的程序是顺序执行,即先执行前面的语句,再执行后面的语句。开发者如果想要控制程序执行的流程,就必须使用流程控制的语法结构,主要是条件执行和循环执行。
if 语句
if语句用于条件判断,满足条件时,就执行指定的语句。
1if (expression) statement
上面式子中,表达式expression为真(值不为0)时,就执行statement语句。
if后面的判断条件expression外面必须有圆括号,否则会报错。语句体部分statement可以是一个语句,也可以是放在大括号里面的复合语句。下面是一个例子。
1if (x == 10) printf("x is 10");
上面示例中,当变量x为10时,就会输出一行文字。对于只有一个语句的语句体,语句部分通常另起一行。
12if (x == 10) printf("x is 10\n");
如果有多条语句,就需要把它们放在大括号里面,组成一个复合语句。
1234if (line_num == MAX_LINES) { line_num = 0; pa ...
运算符
C 语言的运算符非常多,一共有 50 多种,可以分成若干类。
算术运算符
算术运算符专门用于算术运算,主要有下面几种。
+:正值运算符(一元运算符)
-:负值运算符(一元运算符)
+:加法运算符(二元运算符)
-:减法运算符(二元运算符)
*:乘法运算符
/:除法运算符
%:余值运算符
(1)+,-
+和-既可以作为一元运算符,也可以作为二元运算符。所谓“一元运算符”,指的是只需要一个运算数就可以执行。一元运算符-用来改变一个值的正负号。
1int x = -12;
上面示例中,-将12这个值变成-12。
一元运算符+对正负值没有影响,是一个完全可以省略的运算符,但是写了也不会报错。
12int x = -12;int y = +x;
上面示例中,变量y的值还是-12,因为+不会改变正负值。
二元运算符+和-用来完成加法和减法。
12int x = 4 + 22;int y = 61 - 23;
(2)*
运算符*用来完成乘法。
12int num = 5;printf("%i\n", num * num); // 输出 25
(3)/
运算符/ ...
变量
变量(variable)可以理解成一块内存区域的名字。通过变量名,可以引用这块内存区域,获取里面存储的值。由于值可能发生变化,所以称为变量,否则就是常量了。
变量名
变量名在 C 语言里面属于标识符(identifier),命名有严格的规范。
只能由字母(包括大写和小写)、数字和下划线(_)组成。
不能以数字开头。
长度不能超过63个字符。
下面是一些无效变量名的例子。
123456$zjj**p2catHot-tabtax ratedon't
上面示例中,每一行的变量名都是无效的。
变量名区分大小写,star、Star、STAR都是不同的变量。
并非所有的词都能用作变量名,有些词在 C
语言里面有特殊含义(比如int),另一些词是命令(比如continue),它们都称为关键字,不能用作变量名。另外,C
语言还保留了一些词,供未来使用,这些保留字也不能用作变量名。下面就是 C
语言主要的关键字和保留字。
auto, break, case, char, const, continue, default, do, double, else,
enum, exter ...
C 语言基本语法
语句
C
语言的代码由一行行语句(statement)组成。语句就是程序执行的一个操作命令。C
语言规定,语句必须使用分号结尾,除非有明确规定可以不写分号。
1int x = 1;
上面就是一个变量声明语句,声明整数变量x,并且将值设为1。
多个语句可以写在一行。
1int x; x = 1;
上面示例是两个语句写在一行。所以,语句之间的换行符并不是必需的,只是为了方便阅读代码。
一个语句也可以写成多行,这时就要依靠分号判断语句在哪一行结束。
12345int x;x=1;
上面示例中,第二个语句x = 1;被拆成了四行。编译器会自动忽略代码里面的换行。
单个分号也是有效语句,称为“空语句”,虽然毫无作用。
1;
表达式
C
语言的各种计算,主要通过表达式完成。表达式(expression)是一个计算式,用来获取值。
11 + 2
上面代码就是一个表达式,用来获取1 + 2这个算术计算的结果。
表达式加上分号,也可以成为语句,但是没有实际的作用。
128;3 + 4;
上面示例是两个表达式,加上分号以后成为语句。
表达式与语句的区别主要是两点:
语句可以 ...
编译选项
TypeScript
提供了非常多的编译选项,但是官方文档对每一项的解释很抽象,这一章会详细介绍每一个选项的作用,并给出对应的示例。
索引(点击选项跳转到详细介绍):
选项
类型
默认值
描述
allowJs
boolean
false
允许编译 js 文件
allowSyntheticDefaultImports
boolean
false
允许对不包含默认导出的模块使用默认导入。这个选项不会影响生成的代码,只会影响类型检查。
allowJs
允许编译 js 文件。
设置为 true 时,js 文件会被 tsc
编译,否则不会。一般在项目中 js, ts 混合开发时需要设置。
查看示例
123456789101112131415161718# 设置为 true 时,编译后的文件包含 foo.js├── lib│ ├── foo.js│ └── index.js├── src│ ├── foo.js│ └── index.ts├── package.json└── tsconfig.json``````# 设置为 false 时,编译后的文件不包含 foo ...
代码检查
2019 年 1 月,TypeScirpt
官方决定全面采用 ESLint 作为代码检查的工具,并创建了一个新项目 typescript-eslint,提供了
TypeScript 文件的解析器 @typescript-eslint/parser
和相关的配置选项 @typescript-eslint/eslint-plugin
等。而之前的两个 lint 解决方案都将弃用:
typescript-eslint-parser
已停止维护
TSLint
将提供迁移工具,并在 typescript-eslint 的功能足够完整后停止维护
TSLint(Once we consider ESLint feature-complete w.r.t. TSLint, we will
deprecate TSLint and help users migrate to ESLint1)
综上所述,目前以及将来的 TypeScript 的代码检查方案就是 typescript-eslint。
什么是代码检查
代码检查主要是用来发现代码错误、统一代码风格。
在 JavaScript 项目 ...
声明合并
如果定义了两个相同名字的函数、接口或类,那么它们会合并成一个类型:
函数的合并
之前学习过,我们可以使用重载定义多个函数类型:
123456789function reverse(x: number): number;function reverse(x: string): string;function reverse(x: number | string): number | string { if (typeof x === 'number') { return Number(x.toString().split('').reverse().join('')); } else if (typeof x === 'string') { return x.split('').reverse().join(''); }}
接口的合并
接口中的属性在合并 ...