我们继续第二部分《初识C语言》的学习,上一篇学习笔记当中我们详细学习了函数、数组以及常见操作符,今天我们继续后面内容的学习,接下来的内容还包括: 常见关键字 、#define 定义常量和宏 、指针 、结构体。
第二部分 初识C语言
十一、常见关键字
// C语言提供了丰富的关键字,这些关键字都是语言本身预先设定好的,用户自己是不能创造关键字的
// 我们在创建变量的时候应该避免变量名与关键字冲突
/*
C语言的关键字有如下:
auto break case char const continue
default do double else enum extern
for goto if int long register
return short signed sizeof static struct
switch typedef union unsigned void volatile
while float
· 其中我们大概分为几大类
1、与类型相关:auto const char int short long enum float double union struct signed unsigned static void typedef
2、与循环相关:break continue do while for
3、与分支相关:goto if else switch case default
extern —— 声明外部符号
register —— 寄存器
return —— 函数返回
sizeof —— 计算所占内存大小
volatile —— 后期会有介绍
*/
/*
接下来我们学习几个关键字
register —— 寄存器
· 在计算机上,数据都可以储存在哪里?
1、 寄存器 (单位是字节)
2、高速缓存 (单位是MB)
3、内存 (8G/16G)
4、硬盘 (500G/1T)
5、网盘 (几个T)
由 5 - 1 速度越来越快,造价越来越高,空间越来越小
typedef —— 类型重命名
*/
#include<stdio.h>
typedef unsigned int uint; // 将 unsigned int 类型重命名为 uint
int main()
{
register int a = 0; // 建议编译器将变量a放置于寄存器当中,但并不是直接放置于寄存器中
// 如果成功将变量放置于寄存器中,则运行时间将会缩短
unsigned int age = 0; // 定义一个无符号整型
uint high = 0; // 定义了一个无符号整型
// 这里的 age 和 high 是同样类型的
return 0;
}
/*
static(静态的)
· 修饰局部变量 —— 静态局部变量
· 修饰全局变量 —— 静态全局变量
· 修饰函数
*/
#include <stdio.h>
void test()
{
int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
test();
}
return 0;
}
// 上面这段代码是我们好理解的,运行结果是打印 10 个 1
#include <stdio.h>
void test()
{
//static修饰局部变量
static int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
test();
}
return 0;
}
// 这里仅仅是将变量 i 使用 static 进行修饰,运行结果却是打印 1 到 10
// 所以说 static 修饰局部变量改变了变量的生命周期(不影响作用域)
// 让静态局部变量出了作用域还存在,到程序结束,生命周期才结束
/*
我们往往把内存分为栈区、堆区和静态区
· 栈区:存放局部变量、函数参数 (临时变量)
进了作用域创建,出了作用域就释放
· 堆区:动态内存分配(malloc calloc realloc free)
· 静态区:静态变量、全局变量
放在静态区的数据创建后,直到程序结束才释放
也就是说,原本放在栈区上的变量,因为 static 的修饰,存放在了静态区(改变了存储位置)
*/
// 下面我们来看 static 对全局变量的影响
// 在add.c源文件中
int g_val = 2018;
// 在test.c源文件中
extern int g_val;
int main()
{
printf("%d\n", g_val);
return 0;
}
// 这段代码是可以正常运行打印的
// 但如果改成如下这样
// 在add.c源文件中
static int g_val = 2018;
// 在test.c源文件中
int main()
{
printf("%d\n", g_val);
return 0;
}
// 在编译的时候会出现连接性错误
// 结论:一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。
// 全局变量本身是具有外部链接属性的,在 A 文件中定义,在 B 文件可以通过“链接”使用
// 但是如果全局变量被 static 修饰,就从外部链接属性变为了内部链接属性,只能在本文件中使用
// 使得全局变量的作用域变小了
// 下面我们来看 static 对函数的影响
// 在add.c源文件中
int Add(int x, int y)
{
return x + y;
}
// 在test.c源文件中
extern int Add(int x, int y); // 声明外部符号
int main()
{
printf("%d\n", Add(2, 3));
return 0;
}
// 这段代码是可以正常运行的,打印输出 5
// 但如果改成如下这样
// 在add.c源文件中
static int Add(int x, int y)
{
return x + y;
}
// 在test.c源文件中
extern int Add(int x, int y); // 声明外部符号
int main()
{
printf("%d\n", Add(2, 3));
return 0;
}
// 在编译的时候会出现连接性错误
// 结论:一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。
// 函数本身是具有外部链接属性的,被 static 修饰,就从外部链接属性变为了内部链接属性,只能在本文件中使用
// 剩余关键字在后面的学习中都会逐渐遇到逐渐学习
· 关于 EOF 以及 scanf 返回值
// 在这里补充一下关于 EOF 以及 scanf 返回值
// EOF 的本质就是 -1 (end of file)
// scanf 函数读取失败的时候就会返回EOF
// 如果读取正常的话,返回的是读取到的数据的个数
// 比如我们来看下面这段代码的例子
#include<stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int ret = scanf("%d %d", &a, &b);
printf("ret = %d", ret);
printf("a = %d", a);
printf("b = %d", b);
return 0;
}
/*
这段代码在正常情况下 ret 会输出 2
a 和 b 会输出用户输入的数值
但是如果代码输入 Ctrl + Z 进行强制退出
那么 ret 的数值就会显示 -1 即 EOF 的数值
*/
十二、#define定义常量和宏
#define M 100 // 定义符号(标识符常量)
#define MAX(x,y) (x > y ? x : y) // 定义宏 —— 处理相对简单逻辑
// 这个宏也可以写成函数,实现同样功能
int Max(int x ,int y)
{
if (x >= y)
return x;
else
return y;
}
#define ADD(x,y) ((x)+(y)) // 这也是个宏,实现返回两个参数相加
#include<stdio.h>
int main()
{
printf("%d\n", M);
int a = 10;
int b = 20;
int m = MAX(a, b); //使用宏
// 这句话相当于
int m = (a > b ? a : b);
printf("%d\n", m);
return 0;
}
以上是本篇笔记的内容,我们学习了常见关键字以及#define定义常量和宏的相关知识,在接下来的笔记中,我们依旧会继续第二部分的学习,接下来的内容还包括指针和结构体,这两个知识点都是C语言中非常重要的知识,在学习完这两个知识点后,我们会再进行一篇练习文章,从而结束我们第二部分——《初识C语言》的学习。