This commit is contained in:
hairrrrr
2020-03-05 18:24:22 +08:00
parent 32b2fd1c33
commit 580550f9fb

View File

@@ -0,0 +1,366 @@
## C语言基本结构
*Every program is a part of some other program and rarely fits.*[^0]
> 码字不易,对你有帮助 **点赞/转发/关注** 支持一下作者
> 微信搜公众号:**不会编程的程序圆**
> **看更多干货,获取第一时间更新**
### 思维导图
***
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200305164948979.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0OTU0MDEw,size_16,color_FFFFFF,t_70)
###
***
### 写在前面
***
### :email:写在前面
***
如果只是写个人学习总结的博客很容易简单写一些感悟然后贴上代码走人就可以了甚至不用校审。但是我命名本系列为【C语言必知必会】帮助你从入门到精通 C语言那势必要“事无巨细”一些既要考虑到没有基础的初学者又不能止于基础。所以本教程适合各类人群学习只要你看就一定会有帮助。
本教程是本人纯手打并排版,校审由我与我的搭档汤圆君一起完成的。你们看这一篇文章我要写好几个小时。如果文章对你有帮助,请不要“白嫖”。支持一下作者,作者会发更多干货好文。
特别鸣谢汤圆君公众号【Cc听香水榭】 长期更新高质量英语教学)关注她表示对她工作的认可吧!
》 此符号表示该内容以后的章节会讲解,此章节内不要求理解。
### 简单的程序结构
***
下面是一个简单的程序,身高是给出的,体重是在程序中得到的,我们输出的是体重与身高/体重的值。
这里我们更注重的是**程序的结构**而非程序本身。
示例
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200305165553855.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0OTU0MDEw,size_16,color_FFFFFF,t_70)
#### 1. 类型
> 每一个变量都有**类型**type。类型用来描述变量的数据的种类也称**数据类型**。
数值型变量的类型决定了变量所能存储的最大值与最小值,以及是否允许小数点后出现数字。
示例中只有一种数据类型:`int`
> **int**integer即整型表示整数。
数据类型还有很多,目前除了 int 以外,我们只再使用另一种:
> **float**floating-point: 浮点型,可以表示小数
**注意**:虽然 float 型可以带小数,但是进行**算术运算**时float 型要比 int 型慢,而且 float 通常只是一个值的近似值。比如在一个float 型变量中存储 0.1 但其实可能这个变量的值为 0.09999987,这是舍入造成的误差)
*题外话:我当时学的时候,就没有人告诉我这些知识,你们如果现在是初学,我都感觉到羡慕,你们要少走多少弯路啊!*
#### 2. 关键字
> int 与float 都是C语言的**关键字**keyword,关键字是语言定义的单词,**不能用做其他用途**。比如不能用作命名函数名与变量名。
关键字:*斜体代表C99新增关键字*
| auto | enum | unsigned | break | extern |
| ---------- | -------- | -------- | ---------- | ------------ |
| return | void | case | float | short |
| volatile | char | for | signed | while |
| const | goto | sizeof | continue | if |
| static | default | struct | do | int |
| switch | double | long | typedef | else |
| register | union | | | |
| *restrict* | *inline* | *_Bool* | *_Complex* | *_Imaginary* |
如果关键字使用不当(关键字作为变量名),编译器会将其视为语法错误。
> 保留标识符reserved identifier下划线开头的标识符和标准库函数名printf()
C语言已经指定了这些标识符的用途或保留了它们的使用权如果你使用它们作为变量名即使没有语法错误也不能随便使用。
#### 3. 声明
> **声明**declaration在使用变量variable之前必须对其进行声明为编译器所作的描述
>
> 声明的方式为:数据类型 + 变量名(程序员自己决定变量名,命名规则后面会讲)
示例中的 `int weight`完成了两件事情。第一,函数中有个变量名为 weight。第二int 表明这个变量是整型。
编译器用这些信息为变量 weight 在内存中分配空间。
**C99** 前,如果有声明,声明一定要在语句之前。(就像示例那样,函数体中第一块是声明,第二块才是语句。)
C99 和 C11 遵循 C++ 的惯例可以把声明放在任何位置。即可以使用时再声明变量。以后C程序中这种做法可能会很流行。**但是目前不建议这样。**
就**书写格式**而言,我建议将声明全部放在**函数体头部**,声明与语句之间**空出一行**。
#### 4. 命名
> weight,height 都是**标识符**,也就是一个变量,函数或其他实体的名称。因此,声明将特定标识符与计算机内存的特定位置联系起来,同时也就确定了存储在某位置的信息类型或数据类型。
给变量命名时要使用有意义的变量名或标识符。如果变量名无法清楚的表达自身的用途,可以在注释中进一步说明,这是一种良好的编程习惯与编程技巧。
C99 与 C11 允许使用更长的标识符,但是编译器只识别前 63个字符。*对于外部标识符,只允许 31 个字符*。事实上,你可以使用更长的字符,但是编译器可能忽略超出的部分。(比如有两个标识符都是 64 个字符,但只有最后一个字符不同。编译器可能会视其为同一个名字,也可能不会。标准并未定义在这种情况下会发生什么。)
> 命名规则可以用小写字母大写字母数字和下划线_来命名。**名称的第一个字符必须是字符或下划线,不能是数字**
**操作系统和C库经常使用一个下划线或两个下划线开始的标识符_kcab因此最好避免在自己的程序中使用这种名称。避免与操作系统和c库的标识符重复**
C语言的名称区分大小写。即starStarSTAR 是不同的。
**声明变量的理由**
1. 把所有变量放在一处,方便读者查找和理解程序的用途。
2. 声明变量可以促使你在编写程序之前做好计划(比如你的程序要用什么变量,你可以提前规划)。
3. 声明变量有助于发现程序中的小错误,如拼写错误。
4. **不提前声明变量C程序编译将无法通过**
#### 5. 赋值
> 赋值assignment变量通过赋值的方式获得值。
示例中,`weight = 160; `是一个 **赋值表达式语句**。意思是“把值 160 赋给 变量 weight”。
在执行 `int weight;`时,编译器在计算机内存中为变量 weight 预留的空间,然后在执行这行代码时,把值存储在之前预留的位置。可以给 weight 赋不同的值,这就是 weight 之所以被称为变量的原因。
**注意:**
- 该行表达式将值从右侧赋到左侧。
- 该语句以分号结尾。
- `=` 在计算机中不是相等的意思,而是赋值。我们在读 `weight = 160; `时,我们应该这么读:“将 160 赋给 weight”
- `==`表示相等
#### 6. printf() 函数
`printf(“我的体重是:%d斤\n身高与体重的比为%d”, weight, height / weight);`
这是我们示例中的 printf 函数,我们来看两个不那么复杂的:
```c
main(void);
printf("Hi");
```
首先printf() 的 **圆括号**是不是很像 main() ?这表示 printf 是一个函数名,它也是一个函数。圆括号内的内容是从 main() 函数传递给 printf() 函数的信息。该信息被称为**参数**,更确切的说,是**实际参数**actual argument简称**实参**。
既然是函数,它其实也是像我们看到的 main函数一样也有函数头和函数体。
printf() 函数是一个库函数,库函数我们上一节讲函数种类时说过,这是一种不需要程序员去写的,只需要引用头文件 `stdio.h`就可以直接使用的。但是我们应该知道这一点,详细情况我们后面会说讲。
**当程序运行到 printf() 函数这一行时控制权被转给了printf()函数。函数执行结束后控制权被返回至主调函数calling function该例中是 main()**
printf() 函数的作用是向我们的显示器输出内容。
此例中printf() 函数的括号内 分为两部分,一部分在双引号内,另一部分在双引号外,它们中间以逗号隔开。双引号外有两个参数 weight 和 height / weight ,他们分别是变量和**表达式**(含有常量,变量和运算符的式子),也是指定要被打印的参数(打印到你的屏幕上)。
我们发现,最终我们屏幕上看到的是引号内的内容。我们可以来看一下输出的内容:
```c
160
1
```
我们发现:首先引号内的 `%d``\n`并没有被输出,`%d`的位置被替换成了一个整数。为什么会这样呢?
> `\n`代表**一个换行符(newline character)**。对于 printf 函数来说,它的意思是:“**在下一行的最左边开始新的一行**”。
>
> 也就是说换行符和在键盘上按下 Enter按键相同。
>既然如此,为何不在键入 printf() 参数时直接使用 Enter键呢因为编辑器可能认为这是直接的命令而不是存储在源代码中的指令。换句话说如果直接按下 Enter键编辑器会退出当前行并开始新的一行。但是换行符会影响程序输出的显示格式。
换行符是一个**转义序列**escape sequence。转义序列用于难以表示或无法输入的字符。如,`\t`代表 Tab键即制表符。`\b`代表 Backspace键即退格键。我们在后面会继续讨论。
这样就解释了为何一行的printf() 函数会输出两行。
*以下这部分不能理解可以只看结论,能理解更好。*
在解释 %d 之前我们先来看一下weight 和 height / weight 所代表的值。
weight 是被赋值为 160 的,所以 weight 的值就是 160
C语言中`/`表示除法, `*` 表示乘法。
那么 height / weight 的值是多少呢?我们现在不知道这个表达式的值是多少,但是我们知道这个它肯定代表 180 / 160
而最终输出的值是 1 ,这和我们想的不一样,我们知道结果应该是个小数,那么这是为什么呢?
我想可能的原因有两个:
1. %d 将小数转换为整数
2. 180 / 160 本身在C语言中的值就是整数
我们来测试一下:
```c
int main(void) {
int a = 3;
int b = 2;
float c = 1.1f;//f 表示1.1是浮点数
printf("%d\n", c);//%d 用来输出整型
printf("%f\n", a / b);//%f 用来输出浮点型
return 0;
}
```
输出:
```c
-1717986918
0.000000
```
输出并不是我们想要的内容,我们来看一下编译器的警告:
编译器警告:
```c
printf: %dint 1 double
printf: %fdouble 1 int
```
可以不去理解报错的内容。输出与报错至少说明了一点:
**%d 在我的编译器上无法输出浮点型;整型 / 整型 不是浮点型。**
那就说明了原因2是对的**180 / 160 的值就是 1**
为什么 `180 / 160 == 1 `(180 / 160 的值是 1)呢?
因为 weight 和 height 都整数,它们相除结果取整数(向下取整)。
如何输出 float 类型的浮点数?
```c
printf("%f", 2.0f);
```
>`%d`是一个占位符,其作用是指明 num 值的位置。d 代表 以十进制的格式。
还有一点要注意的是在示例中第二个输出的整数的参数height / weight )是一个表达式,我们也可以在程序中添加一个新的变量,然后用这个变量代替上面的表达式作为 printf() 的参数。如:
```c
int main(void)
{
int height = 180;
int weight, scale;//scale:比例
weight = 160;
scale = height / weight;
printf(%d斤\n%d, weight, scale);
return 0;
}
```
合理的使用表达式作为函数的参数可以简化程序。
也说明**在任何需要数值的地方,都可以使用具有相同类型的表达式**。
#### 7. 初始化
当程序开始执行时某些变量会被自动设置为0而大多数不会。没有默认值并且尚未在程序中被赋值的变量时未初始化的uninitialized
如果试图访问未初始化的变量,可能会得到不可预知的值。在某些编译器中,可能会发生更坏的情况(甚至程序崩溃)。
我们可以用赋值的办法给变量赋初值,但还有更简洁的做法:在变量声明中加入初始值。
例如示例中的 `int height = 180`数值 180 就是一个**初始化式**initializer
同一个声明中可以对任意数量的变量进行初始化。如:
```c
int a = 10, b = 15, c = 20;
```
上述每个变量都拥有属于自己的初始化式。接下来的例子,只有 c 有初始化式ab没有。
```c
int a, b, c = 20;
```
***
[^0]: 每个程序都是其他程序不合适的一部分。
*参考资料《C Primer Plus》《C语言程序设计现代方法》*
> 本文GitHub已更新所有教学和练习代码都会上传上去欢迎 star
>
> https://github.com/hairrrrr/C-CrashCourse
***
以上就是本次的内容。
如果文章有错误欢迎指正和补充,感谢!
最后,如果你还有什么问题或者想知道到的,可以在评论区告诉我呦,我可以在后面的文章加上你们的真知灼见。
**关注我**,看更多干货!
我是程序圆,我们下次再见。