【带头学C++】基础知识[入门篇]----1.18 volatile强制访问内存

1.17 register关键字是修饰寄存器变量的,但是在C++11---C++17以后,被弃用了。【简单了解】

并且不再具有实际意义。实际上,编译器会自动为需要使用寄存器的变量选择合适的寄存器。

历史意义:在早期的 C 和 C++ 标准中,register 关键字被用于向编译器指示某个变量应当被尽可能地存储在寄存器中,以便提高程序的执行效率。不过,现代编译器已经具备了更先进的优化能力,并不需要使用 register 关键字来显式指定寄存器

1.18 Volatile强制访问内存

1.什么是volatite?

`volatile` 是 C++ 中的一个关键字,用于标记一个变量是易变的(即可能在意料之外的时刻被修改),以便防止编译器对该变量进行优化

`volatile` 关键字的主要作用是告诉编译器,在对该变量的读写操作时,不要进行某些可能优化的步骤,以保证程序的行为符合预期。

        需要注意的是,`volatile` 并不能保证线程安全性,也不能解决所有并发问题。对于线程安全和并发控制,需要使用其他机制,比如互斥锁或原子操作。

在日常编程中,除非你在并发编程或与外部硬件进行交互,否则使用 `volatile` 的情况相对较少。大多数情况下,编译器的优化能力足以满足需求,而不需要显式地使用 `volatile` 关键字。volatile其实主要就是用来访问特定内存地址映射的io口的。

2.应用场景

在C++中,volatile关键字的应用场景主要包括以下几个方面:

  1. 硬件寄存器访问:在某些嵌入式系统编程中,程序可能需要直接访问硬件的寄存器。由于这些寄存器的值可能会在程序的执行过程中被改变(例如,中断服务例程可能会改变某个寄存器的值),因此,编译器不应优化对这个寄存器的访问。此时,可以将这个寄存器声明为volatile
  2. 多线程并发:在多线程编程中,如果一个变量可能会被多个线程并发修改,那么这个变量就应该被声明为volatile。这是因为,如果编译器认为这个变量只被一个线程访问和修改,那么它可能会对这个变量进行优化(例如,将这个变量的值缓存在CPU的寄存器中),这可能会导致其他线程无法看到这个变量的最新值。
  3. 中断服务例程(ISR):在某些系统中,中断服务例程(ISR)可能会改变某些变量的值。由于ISR的执行是异步的,因此,编译器不能假定在ISR执行期间其他代码不会访问这个变量。因此,如果一个变量可能会在ISR中被改变,那么这个变量应该被声明为volatile
  4. 全局/静态变量初始化:在C++中,全局变量和静态变量的初始化是编译器在编译时进行的。然而,有一些全局/静态变量的初始化可能需要等到运行时才能进行(例如,使用函数malloc动态分配内存)。在这种情况下,编译器需要确保在初始化完成之前,不会对这个变量进行优化。因此,这个变量应该被声明为volatile

需要注意的是,volatile并不能解决所有的并发问题。例如,它作不能解决复合操原子性问题(例如,增加一个计数器的值)。对于这种情况,通常需要使用或者其他同步机制

3.C++20弃用了什么?

        在C++20中,volatile关键字被弃用了一些用法。根据P1152提案,C++20不再允许将volatile用于表示非原子操作类型的变量。这意味着,一些过去使用volatile来表示非原子操作类型的变量,在C++20中不再被允许。具体来说,P1152提案建议使用其他方式来处理非原子操作类型的变量,例如使用atomic类型或者使用其他同步机制(如锁)来确保变量的正确性。需要注意的是,volatile在C++中仍然保留了一些用法,例如用于硬件寄存器访问和多线程并发等场景。

1.19 Sizeof 计算类型占比内存的大小

sizeof 是 C++ 中的一元运算符,用于获取类型或变量在内存中所占用的字节数。

sizeof 运算符可以用于以下几种情况:

1.获取类型的大小

sizeof(int);  // 返回整型 int 的字节数
sizeof(double);  // 返回双精度浮点型 double 的字节数
sizeof(char);  // 返回字符型 char 的字节数

在这种情况下,sizeof 可以直接放置在类型名前面,用于获取指定类型的大小。返回结果是一个常量表达式,通常以 size_t 类型表示。

2.获取变量的大小

int num = 42;
sizeof(num);  // 返回变量 num 的字节数

在这种情况下,sizeof 可以放置在变量名前面,用于获取指定变量的大小。返回结果同样是一个常量表达式。

需要注意的是,sizeof 的结果是在编译时计算的,而不是在运行时。它给出的是指定类型或变量的实际大小,包括数据类型本身的存储空间以及可能存在的对齐补充空间。

此外,sizeof 还可以用于计算数组的大小,例如:

int arr[5];
sizeof(arr);  // 返回整个数组 arr 的字节数,即每个元素大小乘以数组长度

3.在32位系统占不同类型的大小

在 32 位系统和 64 位系统中,C++ 中常见类型的变量所占用的大小是有可能有所不同的。下面是一些常见类型在不同位数系统下的大小表格:

在 32 位系统上:

+----------------+--------+
|   数据类型     | 大小   |
+----------------+--------+
| bool           | 1 字节 |
| char           | 1 字节 |
| short          | 2 字节 |
| int            | 4 字节 |
| long           | 4 字节 |
| long long      | 8 字节 |
| float          | 4 字节 |
| double         | 8 字节 |
| long double    | 12 字节 |
| 指针类型       | 4 字节 |
+----------------+--------+

在 64 位系统上:

+----------------+--------+
|   数据类型     | 大小   |
+----------------+--------+
| bool           | 1 字节 |
| char           | 1 字节 |
| short          | 2 字节 |
| int            | 4 字节 |
| long           | 8 字节 |
| long long      | 8 字节 |
| float          | 4 字节 |
| double         | 8 字节 |
| long double    | 16 字节 |
| 指针类型       | 8 字节 |
+----------------+--------+

此外,C++ 中还存在一些特殊类型、自定义类型和结构体,它们的大小可能会有所不同。可以使用 sizeof 运算符计算所处系统准确的大小信息。

你可能感兴趣的:(C++从基础到抗大旗,1024程序员节,c++,开发语言,数据结构,c语言,笔记)