Skip to content

C++ 修饰符类型

C++ 提供了修饰符来改变基本数据类型的范围或精度,以及限定符来提供关于变量的额外信息,例如它们是否可以被修改。

修饰符置于基本数据类型(如 int, char, double)之前,以针对特定需求对其进行调整。

主要的类型修饰符有:

  • signed:指定该类型可以存储正数、负数和零。这通常是整型 (int, short, long, long long) 的默认值,但可以显式指定。
  • unsigned:指定该类型只能存储非负值(零和正数)。这有效地将最大正数的值范围相比于其对应的有符号类型扩大了一倍,因为符号位用于表示数值大小。
  • short:通常减小 int 的存储大小,导致值范围变小。保证至少 16 位。
  • long:通常增加 int 或 double 的存储大小。long int 保证至少 32 位。
  • long long:(C++11 引入)保证整型至少 64 位,提供比 long int 更宽的范围。

适用范围:

  • signed 和 unsigned 可以应用于 char, short int, int, long int, long long int。
  • short 和 long 应用于 int。
  • long 也可以应用于 double(产生 long double,通常提供更高的精度)。
  • long long 应用于 int。

C++ 允许使用简写形式。例如,unsigned 暗示 unsigned int,short 暗示 short int,long 暗示 long int,而 long long 暗示 long long int。

unsigned short us; // unsigned short int
long li; // long int
unsigned long long ull; // unsigned long long int

有符号类型和无符号类型对位模式的解释不同,尤其是在接近范围极限的值上。

#include <iostream>
int main() {
short int i; // 有符号 short(通常为 16 位,范围 -32768 到 32767)
unsigned short int j; // 无符号 short(通常为 16 位,范围 0 到 65535)
j = 50000;
// 将一个大的无符号值赋给有符号变量
// 可能导致实现定义的行为或回绕(wrap-around)。
i = j;
std::cout << "Signed short i: " << i << std::endl;
std::cout << "Unsigned short j: " << j << std::endl;
return 0;
}

可能的输出(取决于编译器和系统架构):

Signed short i: -15536
Unsigned short j: 50000

解释:在 unsigned short 中表示 50000 的位模式(在 16 位系统上为二进制 11000011 01010000),当作为 signed short 读取时,会被解释为一个负数(-15536)(由于使用了补码表示)。如果值可能超出目标类型的范围,应避免这种有符号和无符号类型之间的隐式转换。

类型限定符提供关于变量的额外信息,主要涉及其可变性以及其值如何变化。

限定符含义
const声明一个对象,其值在初始化后不能更改。对于编写更安全、更具表达力的代码(常量正确性)至关重要。有助于编译器优化。
volatile指示变量的值可能由编译器无法检测到的方式更改(例如,由外部事件更新的硬件寄存器,线程之间未进行适当同步共享的变量)。它告诉编译器不要优化掉对该变量的读写操作。
constexpr (C++11)指定变量或函数可以在编译时求值。用于定义真正的编译时常量和函数。

注意:

  • 应广泛使用 const 来防止意外修改。
  • 在现代 C++ 中,volatile 使用得较少,尤其是在用于线程同步的 std::atomic 出现之后。它的主要用途仍然是内存映射硬件访问。
  • 在旧的 C 标准中提到的 restrict 关键字不是标准 C++ 的一部分,尽管有些编译器可能将其作为扩展支持。它的作用(与指针别名相关)在 C++ 优化中以不同方式或隐式处理。
  • constexpr 是一个强大的特性,用于编译时计算和定义常量。
#include <iostream>
int main() {
const double PI = 3.14159; // 之后不能改变 PI 的值
// PI = 3.14; // 错误:对只读变量 'PI' 的赋值
volatile int hardwareStatusRegister = 0; // 值可能会意外改变
constexpr int compileTimeValue = 2 * 10; // 在编译时求值
std::cout << "PI: " << PI << std::endl;
std::cout << "Initial Hardware Status: " << hardwareStatusRegister << std::endl;
std::cout << "Compile-time value: " << compileTimeValue << std::endl;
return 0;
}