mirror of
https://github.com/Aexiar/c.git
synced 2024-10-22 14:05:45 +02:00
2024年10月8日 16:36
This commit is contained in:
parent
3067a36245
commit
a9762cb7cb
@ -1795,15 +1795,15 @@ int main() {
|
||||
|
||||
| 类别 | 作用域 |
|
||||
| -------- | ------------------------------------------------------------ |
|
||||
| 局部变量 | 局部变量的生存周期仅限于定义它们的函数或代码块的执行时间。<br>它们在函数或代码块执行结束后会被销毁。 |
|
||||
| 局部变量 | 局部变量的生存周期仅限于定义它们的函数或代码块。<br>它们在函数或代码块执行结束后会被销毁。 |
|
||||
| 全局变量 | 全局变量的生命周期从程序开始运行直到程序结束。 <br/>它们在程序整个运行期间都存在。 |
|
||||
|
||||
* 初始值对比:
|
||||
|
||||
| 类别 | 作用域 |
|
||||
| -------- | ------------------------------------------------------------ |
|
||||
| 局部变量 | 系统不会对其默认初始化,必须对局部变量初始化后 才能使用。<br>否则,程序运行后可能会异常退出。 |
|
||||
| 全局变量 | 如果没有显式初始化,它们会被自动、默认初始化为 零或空值,具体取决于数据类型。<br>int 类型的默认初始化值是 0 。<br>char 类型的默认初始化值是 '\0' 或 0 。<br>float 类型的默认初始化值是 0.0f 。<br/>double 类型的默认初始化值是 0.0 。<br/>指针的默认初始化值是 NULL 或 nullptr 。 |
|
||||
| 局部变量 | 系统不会对其默认初始化,必须对局部变量初始化后才能使用。<br>否则,程序运行后可能会异常退出。 |
|
||||
| 全局变量 | 如果没有显式初始化,它们会被自动、默认初始化为零或空值,具体取决于数据类型。<br>int 类型的默认初始化值是 0 。<br>char 类型的默认初始化值是 '\0' 或 0 。<br>float 类型的默认初始化值是 0.0f 。<br/>double 类型的默认初始化值是 0.0 。<br/>指针的默认初始化值是 NULL 或 nullptr 。 |
|
||||
|
||||
* 内存中的位置对比:
|
||||
|
||||
@ -1834,10 +1834,10 @@ int main() {
|
||||
* 动态存储方式:在程序运行期间根据需要进行`动态的分配存储空间`的方式,数据存放在`动态存储区` ,即:`栈`。
|
||||
* 在动态存储区中存放以下数据:
|
||||
* 函数形参:在调用函数时给形参分配存储空间。
|
||||
* 函数中定义的局部变量且没有用关键字 static 声明的变量,即自动变量。
|
||||
* 函数中定义的局部变量且没有用关键字 `static` 声明的变量,即自动变量。
|
||||
* 函数调用时的返回地址等。
|
||||
|
||||
* 在调用该函数时,系统会给这些变量分配存储空间,在函数调用结束时就自动释放这些存储空间。因此这类局部变量称为自动变量。 自动变量用关键字 auto 作存储类别的声明。
|
||||
* 在调用该函数时,系统会给这些变量分配存储空间,在函数调用结束时就自动释放这些存储空间。因此这类局部变量称为自动变量。 自动变量用关键字 `auto` 作为存储类别的声明。
|
||||
* 语法:
|
||||
|
||||
```c
|
||||
@ -1917,11 +1917,155 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 3.3 其它变量修饰符(了解)
|
||||
|
||||
### 3.3.1 寄存器变量(register 变量)
|
||||
|
||||
* 一般情况下,变量(包括静态存储方式和动态存储方式)的值是存放在内存中的。当程序中用到哪一个变量的值时,由控制器发出指令将内存中该变量的值送到运算器中。经过运算器进行运算,如果需要存数,再从运算器将数据送到内存存放。
|
||||
* 如果有一些变量使用频繁(例如,在一个函数中执行 10 000 次循 环,每次循环中都要引用某局部变量),则为存取变量的值要花费不少时间。为提高执行效率,C 语言允许将局部变量的值放在 CPU 中的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存中去存取。由于对寄存器的存取速度远高于对内存的存取速度,因此这 样做可以提高执行效率。这种变量叫做寄存器变量,用关键字`register`作声明。
|
||||
* 语法:
|
||||
|
||||
```c
|
||||
register 数据类型 变量 = 初始化值;
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> * ① 由于现在的计算机的速度愈来愈快,性能愈来愈高, 优化的编译系统能够识别使用频繁的变量,从而自动地将这些变量放在寄存器中,而不需要程序设计者指定。
|
||||
> * ② 因此,现在实际上用 register 声明变量的必要性不大。
|
||||
|
||||
### 3.3.2 const 修饰变量
|
||||
|
||||
#### 3.3.2.1 概述
|
||||
|
||||
* 在 C 语言中, const 关键字用于创建常量,它指示编译器将标识符 (变量、参数、函数等)视为不可修改的值。
|
||||
|
||||
#### 3.3.2.2 常量声明
|
||||
|
||||
* 如果一个变量使用 const 修饰,就变为常量,语法如下:
|
||||
|
||||
```c
|
||||
const int MAX_NUM = 100;
|
||||
```
|
||||
|
||||
* 常量一旦被创建后其值就不能再改变,必须在定义的同时赋值(初始化),后面的任何赋值行为都将引发错误。
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> 通常而言,常量名建议使用大驼峰的形式表示,如:`MAX_VALUE`,以便和普通的局部变量区分。
|
||||
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```c {11}
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
|
||||
// 禁用 stdout 缓冲区
|
||||
setbuf(stdout, nullptr);
|
||||
|
||||
const double PI = 3.14;
|
||||
|
||||
// 错误,不能修改常量
|
||||
PI = 3.1415; // [!code error]
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.3.2.3 指向常量的指针
|
||||
|
||||
* const 也可以和指针变量一起使用,这样可以限制指针变量本身,也可以限制指针指向的数据。const 和指针一起使用会有几种不同的顺序,如下所示:
|
||||
|
||||
```c
|
||||
const int *p1;
|
||||
```
|
||||
|
||||
```c
|
||||
int const *p2;
|
||||
```
|
||||
|
||||
```c
|
||||
int * const p3;
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> 技巧:
|
||||
>
|
||||
> * ① const 离变量名近,就是用来修饰指针变量的,即:`const` 在 `*` 号之后,表示 **指针本身不能改变,但指向的值可以改变**。
|
||||
> * ② const 离变量名远,就是用来修饰指针指向的数据,即: `const` 在 `*` 号之前,表示 **指向的值不能修改,但是指针本身可以修改**。
|
||||
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
|
||||
// 禁用 stdout 缓冲区
|
||||
setbuf(stdout, nullptr);
|
||||
|
||||
const int a = 10;
|
||||
const int b = 20;
|
||||
const int *p1 = &a;
|
||||
// 错误,不能通过 p1 修改 a 的值
|
||||
*p1 = 30; // [!code error]
|
||||
p1 = &b; // 合法:可以让 p1 指向 b
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
|
||||
// 禁用 stdout 缓冲区
|
||||
setbuf(stdout, nullptr);
|
||||
|
||||
const int a = 10;
|
||||
const int b = 20;
|
||||
int const *p2 = &a;
|
||||
// 错误,不能通过 p2 修改 a 的值
|
||||
*p2 = 30; // [!code error]
|
||||
p2 = &b; // 合法:可以让 p2 指向 b
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
|
||||
// 禁用 stdout 缓冲区
|
||||
setbuf(stdout, nullptr);
|
||||
|
||||
const int a = 10;
|
||||
const int b = 20;
|
||||
int *const p3 = &a;
|
||||
// 错误,不能通过 p3 的指向
|
||||
p3 = &b; // [!code error]
|
||||
*p3 = 30; // 合法:可以修改 a 的值
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user