【C语言趣味教程】(4) 变量:代码注释 | 变量的声明 | 初始化与赋值 | 作用域与生命周期 | 局部变量与全局变量
🔗 《C语言趣味教程》👈 猛戳订阅!!!
—— 热门专栏《维生素C语言》的重制版 ——
- 💭 写在前面:这是一套 C 语言趣味教学专栏,目前正在火热连载中,欢迎猛戳订阅!本专栏保证篇篇精品,继续保持本人一贯的幽默式写作风格,当然,在有趣的同时也同样会保证文章的质量,旨在能够产出 "有趣的干货" !本系列教程不管是零基础还是有基础的读者都可以阅读,可以先看看目录! 标题前带星号 (*) 的部分不建议初学者阅读,因为内容难免会超出当前章节的知识点,面向的是对 C 语言有一定基础或已经学过一遍的读者,初学者可自行选择跳过带星号的标题内容,等到后期再回过头来学习。值得一提的是,本专栏 强烈建议使用网页端阅读! 享受极度舒适的排版!你也可以展开目录,看看有没有你感兴趣的部分!希望需要学 C 语言的朋友可以耐下心来读一读。最后,可以订阅一下专栏防止找不到。
" 有趣的写作风格,还有特制的表情包,而且还干货满满!太下饭了!"
—— 沃兹基硕德
📜 本章目录:
Ⅰ. 代码注释(Comment)
0x00 引入:注释的作用
0x01 块注释 /* */
0x02 行注释 //
0x03 保持注释的美观性
Ⅱ. 变量(Variable)
0x00 变量的声明
0x01 多变量声明
0x02 变量的初始化
0x03 多变量声明的初始化
0x04 变量的赋值
0x05 变量重定义引发的报错
Ⅲ. 作用域(Scope)
0x00 引入:变量的作用域
0x01 全局变量和局部变量
0x02 局部变量优先原则
0x03 利用大括号限制变量作用域
0x04 生命周期
Ⅰ. 代码注释(Comment)
0x00 引入:注释的作用
"程序员最讨厌两种人:一种是不写注释的人,一种是让我写注释的人。"
相信大家对注释早已有所耳闻,对于注释,C 语言有两种注释风格,我们下面会逐个讲解。
但在这之前,我们先来了解了解注释的作用,注释就是用于解释代码的文字的。
注释通常用于版本、版权声明,函数接口说明,重要的的代码行或段落提示。
它的存在能够有效提高代码的阅读性,注释不仅仅是给别人看的,也是给自己看的!
特别是写项目的时候。不写注释,几天后可能自己都不知道自己写了什么……
0x01 块注释 /* */
块注释是 C 语言风格的注释,是一对 "斜杠星号"。
内容判定范围为从 /* 开始 到 */ 结束,是成对判定的。
/* 注释内容 */
它可以注释一行内容,也可以注释多行内容:
#include <stdio.h>
int main(void)
{
printf("你好!"); /* 打印你好 */
return 0;
}
/*
这是一套 C 语言趣味教学专栏,
目前正在火热连载中,
欢迎猛戳订阅!本专栏保证篇篇精品,
继续保持本人一贯的幽默式写作风格,
当然,在有趣的同时也同样会保证文章的质量,
旨在能够产出 "有趣的干货" !
*/ int a;
最后的 int a 自然不在注释范围内,判定范围为从 /* 开始 到 */ 结束:
📌 注意:块注释不能嵌套注释:warning C4138: 在注释外找到“*/” error C2059: 语法错误:“/
0x02 行注释 //
行注释是 C++ 风格的注释,是两个斜杠。
内容判定范围从 // 开始到本行结束:
// 注释内容
行注释是非常方便快捷的,只需要在语句后面随手加两个斜杠就行:
#include <stdio.h>
int main(void)
{
printf("你好!"); // 打印你好
return 0;
}
行注释是支持嵌套注释的,比如我们想把这里的 printf 这行注释掉:
#include <stdio.h>
int main(void)
{
// printf("你好!"); // 打印你好
return 0;
}
❓ 那到底哪种注释风格好呢?
行注释和块注释 这两种注释风格并无好坏之分,可以混合使用。
在需要写大量说明的地方使用块注释(比如写函数功能),行内代码可以用行注释,方便快捷。
程序块注释常采用 /* */ ,行注释一般采用 //,举个例子:
/* 启动一个新的线程,运行一个从FILENAME加载的用户程序。
* FILENAME中加载的用户程序。 这个新的线程可以在
* process_execute()返回之前被安排(甚至可以退出)
* 在process_execute()返回之前。 返回新进程的
* 线程ID,如果不能创建线程,则返回TID_ERROR。
*/
tid_t process_execute (
const char *file_name /* FILENAME 加载的程序 */
)
{
tid_t tid; // 记录线程ID
struct file *FILE = NULL; // 创建file指针,用于 filesys_open
char* palloc_file_name = NULL; // FILENAME
char* strtok_tmp; // 临时存储FILENAME
char* ptr; // 用于字符串分割函数
/* 这里创建一个FILE_NAME的副本,是为了阻止调用者与load()发生线程竞争。
* tips: 同一个进程中的线程能够共享进程中的绝大多数资源,当它们进行随意的竞争时,
* 就会导致共享的资源被破坏、脏数据、不完整、不一致等问题。
*/
// 创建一个FILENAME的副本,从用户或内核内存池中获取页
char* fn_copy = palloc_get_page (0);
if (fn_copy == NULL) { // 如果是空页,就返回线程ID错误信息
return TID_ERROR;
}
0x03 保持注释的美观性
在使用行注释时,我们一般习惯在 // 后面加一个空格,因为这样可能会更加美观:
在使用块注释写大量内容时,可以在每行都加上星号:
当然,这些归根结底都是按照个人习惯来。
就像小学学方程写未知数 时,老师并不会强制要求你怎么写。
Ⅱ. 变量(Variable)
- 在讲解整型的章节中,我们已经对变量有一个简单的介绍了。本章我们将详细介绍变量,并且引入常量的知识点。
0x00 变量的声明
变量 (variable),顾名思义就是 "可以变的量"。
我们说过,C 语言的变量是由明确类型的,创建一个变量需要明确该变量的类型。
变量的声明方式有两种,第一种就是我们在前几章介绍的,通过 类型 + 变量名 定义一个变量:
数据类型 变量名;
💬 代码演示:定义变量
#include <stdio.h>
int main()
{
int age;
float height;
double weight;
return 0;
}
这种方式一行只定义一个变量,是最常见且推荐的变量声明方式。
0x01 多变量声明
C 语言还支持 多变量声明,即一行同时定义多个变量,类型 + 变量1, 变量2...
变量类型 变量1, 变量2, 变量3... ;
多变量声明时,变量和变量之间用逗号 ; 分隔。
使用多变量声明就意味着这一行要定义的变量的类型是相同的。
换句话来说,如果我们定义变量的类型都相同,我们就可以使用多变量声明一次定义多个变量。
💬 代码演示:使用多变量声明定义变量
#include <stdio.h>
int main()
{
int a, b, c, d; // 同时定义变量 abcd
return 0;
}
多变量声明还有更多的细节,我们稍后讲解完变量的初始化后再做探讨。
0x02 变量的初始化
变量 初始化 (initialization),就是在定义变量的同时给变量设置一个初始值,我们称为 "赋初值"。
数据类型 变量名 = 初始值;
建议在定义变量时给变量设置初始值,虽然不赋值也是允许的,但是我们不建议这么做!
int a = 0; // 设置初始值
int b; // 不推荐
比如我们定义整型变量 a,我们在定义的时候就随手给它设为 0,这就完成了赋初值的工作。
❓ 思考:如果不设置初始值会怎么样?
如果定义变量没有初始化,那么变量有可能赋值,有可能没赋值。
如果定义的变量是局部变量,那么 编译器可能会给没赋值的初始变量赋一个 "随机值"。
不仅如此,如果你强行 printf 打印 a,会引来报错:error C4700: 使用了未初始化的局部变量“a”
💬 代码演示:打印未初始化的变量
#include <stdio.h>
int main()
{
int a;
printf("%d\n", a);
return 0;
}
🚩 运行结果:error
所以我们需要培养一个好的编程习惯,在定义变量的同时,就给变量初始化。
并且我们 "习惯" 给变量初始值设为 0,下面给一些例子:
int a = 0;
char c = 0;
float f = 0.0;
double d = 0.0;
0x03 多变量声明的初始化
我们先来看下面的初始化,这是常规的初始化方法,创建变量 i, j, k 并初始化为 0。
int i = 0;
int j = 0;
int k = 0;
现在 i, j, k 变量的值都为 0 了,我们刚才说了,C 语言支持多变量类型。
如果我们想达到相同的效果,多变量声明的初始化方式如下:
int i = 0, j = 0, k = 0;
这样,我们的 i, j, k 的值在定义的同时就初始化为 0 了。
📌 注意:我们来看下面这种初始化方式
int main(void)
{
int i, j, k = 0;
return 0;
}
🚩 运行结果如下:(弹出 warning)
如果这么写,那么只有 k 设置了初始值 0,而 i 和 j 是没有初始化的。
0x04 变量的赋值
给已经定义的变量设置一个值,或重新设置一个值,称为 赋值 (assignment) 。
如果我们在定义变量的时候没有给上初始值,我们可以在变量定义后给它赋上一个值:
int a;
a = 10;
通过赋值后,此时变量 a 就有值了。
当然,变量在定义的时候就完成初始化了,此时我们也可以给变量赋上一个新值:
int b = 0; // 定义变量并初始化
b = 10;
我们给 b 赋值后,此时变量 b 的值不是初始化给的 0 了,而是 10 了。
💬 代码演示:赋值前和赋值后
#include <stdio.h>
int main(void)
{
int a = 0;
printf("赋值前: %d\n", a);
a = 10;
printf("赋值后: %d\n", a);
return 0;
}
🚩 运行结果如下:
当然,也是支持多变量赋值的:
#include <stdio.h>
int main(void)
{
int a = 0, b = 0, c = 0;
printf("赋值前: %d %d %d\n", a, b, c);
a = 10, b = 20, c = 30;
printf("赋值后: %d %d %d\n", a, b, c);
return 0;
}
🚩 运行结果如下:
0x05 变量重定义引发的报错
我们先看看下面的代码:
#include <stdio.h>
int main(void)
{
int a;
int a;
int b = 10;
int b = 20;
return 0;
}
可以看到,变量 a 和 b 定义了两次,这在 C 语言中是明令禁止的,引发 重定义问题 。
会引发如下报错:error C2086: “int a”: 重定义,error C2374: “b”: 重定义;多次初始化
Ⅲ. 作用域(Scope)
0x00 引入:变量的作用域
变量和常量在程序中都是有作用范围的,这个范围我们称之为变量的 作用域 (scope) 。
(常量的概念我们下一章讲解)变量的作用域又可以分为 全局作用域 和 局部作用域。
0x01 全局变量和局部变量
在函数内部声明或定义的变量称之为 全局变量 (global variable) 。
全局变量的作用域在整个工程。
在函数内部声明或定义的变量称为 局部变量 (local variable) 。
局部变量的作用域仅在该函数的内部,出了函数就无效。
#include <stdio.h>
int A = 10; // 全局变量
int main(void)
{
int a = 20; // 局部变量
return 0;
}
❓ 如何快速分辨全局变量和局部变量?最简单的方法就是看大括号!
- 大括号外部定义的变量叫做 全局变量。
- 大括号内部定义的变量叫做 局部变量 。
0x02 局部变量优先原则
当局部变量和全局变量的名字相同时,局部变量优先。
💬 代码演示:局部变量优先
#include <stdio.h>
int var = 100; // 全局变量
int main(void)
{
int var = 10; // 局部变量
printf("%d\n", var);
return 0;
}
🚩 运行结果如下:
0x03 利用大括号限制变量作用域
使用大括号可以限制一个变量的作用域,在大括号内的变量就是局部变量。
其作用范围仅仅在这个打括号内,出了这个大括号就无效。
💬 代码演示:使用大括号限制变量的作用域
#include <stdio.h>
int main(void)
{
int a = 0;
{
int a = 10;
printf("大括号内 a 的值:%d\n", a);
}
printf("大括号外 a 的值:%d\n", a);
return 0;
}
🚩 运行结果如下:
这里仍然遵循局部变量优先原则,局部变量优先。
0x04 生命周期
变量创建和销毁之间的时间段,称为 生命周期 (Life Cycle)。
全局变量的生命周期和局部变量的生命周期是不同的:
- 全局变量:整个程序的生命周期。
- 局部变量:进入作用于生命周期开始,出了作用域生命周期结束。
💬 代码演示:局部变量的生命周期
#include <stdio.h>
int main(void)
{
{
int a = 10;
printf("%d\n", a);
}
printf("%d\n", a); // 出了作用域了
}
🚩 运行结果:(报错)
📌 [ 笔者 ] 王亦优 | 雷向明
📃 [ 更新 ] 2023.7.10
❌ [ 勘误 ] /* 暂无 */
📜 [ 声明 ] 由于作者水平有限,本文有错误和不准确之处在所难免,
本人也很想知道这些错误,恳望读者批评指正!
📜 参考文献: - C++reference[EB/OL]. []. http://www.cplusplus.com/reference/. - Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. . - 百度百科[EB/OL]. []. https://baike.baidu.com/. - 维基百科[EB/OL]. []. https://zh.wikipedia.org/wiki/Wikipedia - R. Neapolitan, Foundations of Algorithms (5th ed.), Jones & Bartlett, 2015. - B. 比特科技. C/C++[EB/OL]. 2021[2021.8.31] - 林锐博士. 《高质量C/C++编程指南》[M]. 1.0. 电子工业, 2001.7.24. - 陈正冲. 《C语言深度解剖》[M]. 第三版. 北京航空航天大学出版社, 2019. - 侯捷. 《STL源码剖析》[M]. 华中科技大学出版社, 2002. - T. Cormen《算法导论》(第三版),麻省理工学院出版社,2009年。 - T. Roughgarden, Algorithms Illuminated, Part 1~3, Soundlikeyourself Publishing, 2018. - J. Kleinberg&E. Tardos, Algorithm Design, Addison Wesley, 2005. - R. Sedgewick&K. Wayne,《算法》(第四版),Addison-Wesley,2011 - S. Dasgupta,《算法》,McGraw-Hill教育出版社,2006。 - S. Baase&A. Van Gelder, Computer Algorithms: 设计与分析简介》,Addison Wesley,2000。 - E. Horowitz,《C语言中的数据结构基础》,计算机科学出版社,1993 - S. Skiena, The Algorithm Design Manual (2nd ed.), Springer, 2008. - A. Aho, J. Hopcroft, and J. Ullman, Design and Analysis of Algorithms, Addison-Wesley, 1974. - M. Weiss, Data Structure and Algorithm Analysis in C (2nd ed.), Pearson, 1997. - A. Levitin, Introduction to the Design and Analysis of Algorithms, Addison Wesley, 2003. - A. Aho, J. - E. Horowitz, S. Sahni and S. Rajasekaran, Computer Algorithms/C++, Computer Science Press, 1997. - R. Sedgewick, Algorithms in C: 第1-4部分(第三版),Addison-Wesley,1998 - R. Sedgewick,《C语言中的算法》。第5部分(第3版),Addison-Wesley,2002 |