C++ 变量和数据类型示例

功能描述

这是一个展示 C++ 中各种变量类型和数据类型的示例程序。它演示了基本数据类型、无符号整数、大整数、固定宽度整数类型、常量、类型转换、变量作用域、变量初始化以及类型别名等概念。

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <string>
#include <cstdint>

int main() {
// 基本数据类型
int age = 25;
float height = 1.75f;
double price = 19.99;
char grade = 'A';
bool isStudent = true;
std::string name = "John Doe";

// 输出变量值
std::cout << "Name: " << name << std::endl;
// ... 其他输出语句 ...

return 0;
}

数据类型详解

基本数据类型

类型 大小 范围 示例
int 通常4字节 -2,147,483,648 到 2,147,483,647 int age = 25;
float 4字节 约 ±3.4e38 float height = 1.75f;
double 8字节 约 ±1.7e308 double price = 19.99;
char 1字节 -128 到 127 或 0 到 255 char grade = 'A';
bool 通常1字节 truefalse bool isStudent = true;
std::string 可变 字符串 std::string name = "John Doe";

无符号和大整数类型

类型 大小 范围 示例
unsigned int 通常4字节 0 到 4,294,967,295 unsigned int unsignedNum = 42;
long long 8字节 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 long long largeNumber = 9223372036854775807LL;
unsigned long long 8字节 0 到 18,446,744,073,709,551,615 unsigned long long ulargeNumber = 18446744073709551615ULL;

固定宽度整数类型 (C++11+)

类型 大小 范围 示例
int8_t 1字节 -128 到 127 int8_t smallInt = -128;
uint8_t 1字节 0 到 255 uint8_t unsignedSmallInt = 255;
int16_t 2字节 -32,768 到 32,767 int16_t mediumInt = 32767;
uint16_t 2字节 0 到 65,535 uint16_t unsignedMediumInt = 65535;
int32_t 4字节 -2,147,483,648 到 2,147,483,647 int32_t normalInt = -2147483648;
uint32_t 4字节 0 到 4,294,967,295 uint32_t unsignedNormalInt = 4294967295;
int64_t 8字节 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 int64_t bigInt = -9223372036854775808LL;
uint64_t 8字节 0 到 18,446,744,073,709,551,615 uint64_t unsignedBigInt = 18446744073709551615ULL;

常量

类型 描述 示例
const 运行时常量 const int MAX_VALUE = 100;
constexpr 编译时常量 (C++11+) constexpr double PI = 3.14159265359;

编译和运行

在 Windows 上编译(使用 g++):

1
g++ -std=c++11 -fexec-charset=GBK -o variables variables.cpp

运行程序:

1
.\variables.exe

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
=== 基本数据类型 ===
Name: John Doe
Age: 25
Height: 1.75m
Price: $19.99
Grade: A
Is Student: Yes

=== 无符号和大整数类型 ===
Unsigned: 42
Large Number: 9223372036854775807

=== 固定宽度整数类型 ===
int8_t: -128
uint8_t: 255
int16_t: 32767
uint16_t: 65535
int32_t: -2147483648
uint32_t: 4294967295
int64_t: -9223372036854775808
uint64_t: 18446744073709551615

=== 常量 ===
MAX_VALUE: 100
PI: 3.14159

=== 类型转换 ===
Implicit conversion (int to double): 103.14
Explicit conversion (double to int): 3
C-style conversion (double to int): 3

=== 变量的作用域 ===
Local variable: 20
Global-like variable inside block: 10
Global-like variable outside block: 10

=== 变量的初始化 ===
a: 1
b: 2
c: 3
d: 4
e: 0

=== 类型别名 ===
typedef unsigned long: 123456789
using unsigned int: 987654321

=== 字符串类型 ===
C-style string: Hello C-style string
C++ string: Hello C++ string
C++ string length: 16

技术要点

1. 变量声明和初始化

C++ 中变量的声明和初始化方式有多种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 拷贝初始化
int a = 1;

// 直接初始化
int b(2);

// 列表初始化 (C++11+)
int c{3};

// 拷贝列表初始化 (C++11+)
int d = {4};

// 值初始化 (C++11+)
int e{};

2. 类型转换

隐式类型转换

当两种类型兼容时,C++ 会自动进行类型转换:

1
2
3
int integer = 100;
double floating = 3.14;
double result = integer + floating; // int 自动转换为 double

显式类型转换

使用 static_cast 进行类型转换:

1
2
double floating = 3.14;
int result = static_cast<int>(floating); // 显式转换 double 为 int

C风格类型转换

C++ 也支持 C 风格的类型转换:

1
2
double floating = 3.14;
int result = (int)floating; // C风格转换

3. 变量的作用域

变量的作用域决定了它在程序中的可见性:

1
2
3
4
5
6
7
int globalLike = 10; // 在 main 函数作用域内可见
{
int local = 20; // 只在这个代码块内可见
std::cout << local << std::endl; // 正确
}
std::cout << globalLike << std::endl; // 正确
// std::cout << local << std::endl; // 错误,local 在此处不可见

4. 类型别名

C++ 提供了两种方式创建类型别名:

1
2
3
4
5
6
7
// 使用 typedef
typedef unsigned long ulong;
ulong number1 = 123456789;

// 使用 using (C++11+)
using uint = unsigned int;
uint number2 = 987654321;

5. 字符串类型

C++ 提供了两种字符串表示方式:

1
2
3
4
5
// C风格字符串
char cString[] = "Hello C-style string";

// C++字符串 (推荐)
std::string cppString = "Hello C++ string";

std::string 是一个类,提供了许多有用的方法,如 length()append()substr() 等。

常见问题

1. 整数溢出

当整数超出其类型的范围时,会发生溢出:

1
2
int maxInt = 2147483647;
maxInt++; // 溢出,结果未定义

解决方案:使用更大范围的整数类型,如 long long 或固定宽度整数类型。

2. 浮点数精度问题

浮点数有精度限制:

1
2
3
float f = 0.1;
double d = 0.1;
// f 和 d 可能不完全等于 0.1

解决方案:对于需要高精度的计算,使用 double 而不是 float,或考虑使用专门的库。

3. 类型不匹配

当尝试将一种类型的值赋给不兼容的类型时:

1
int x = "hello"; // 错误,类型不匹配

解决方案:确保类型匹配或使用适当的类型转换。

4. 未初始化的变量

使用未初始化的变量会导致未定义行为:

1
2
int x;
std::cout << x; // 未定义行为

解决方案:始终初始化变量。

代码优化建议

  1. 使用固定宽度整数类型:在需要精确控制大小的情况下,使用 std::int32_tstd::uint64_t 等固定宽度类型。

  2. 优先使用 constexpr:对于编译时常量,使用 constexpr 而不是 const

  3. 使用列表初始化:列表初始化可以防止窄化转换:

1
2
int x = 3.14; // 允许,会截断
int y{3.14}; // 错误,防止窄化转换
  1. 避免使用 C 风格类型转换:使用 static_castdynamic_castconst_castreinterpret_cast 代替 C 风格转换。

  2. 使用 std::string:对于字符串操作,优先使用 std::string 而不是 C 风格字符串。

总结

C++ 提供了丰富的数据类型和变量声明方式,包括:

  • 基本数据类型:intfloatdoublecharbool
  • 无符号和大整数类型:unsigned intlong long
  • 固定宽度整数类型:int8_tuint16_t
  • 常量:constconstexpr
  • 字符串:std::string

了解这些数据类型及其特性对于编写正确、高效的 C++ 代码至关重要。通过适当选择数据类型,可以提高程序的性能、可靠性和可读性。

variables.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <iostream>
#include <string>
#include <cstdint>
#include <climits>


int main() {
// 基本数据类型
int age = 25;
float height = 1.75f;
double price = 19.99;
char grade = 'A';
bool isStudent = true;
std::string name = "John Doe";

std::cout << "=== 基本数据类型 ===" << std::endl;
std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << std::endl;
std::cout << "Height: " << height << "m" << std::endl;
std::cout << "Price: $" << price << std::endl;
std::cout << "Grade: " << grade << std::endl;
std::cout << "Is Student: " << (isStudent ? "Yes" : "No") << std::endl;

// 无符号和大整数类型
unsigned int unsignedNum = 42;
long long largeNumber = 9223372036854775807LL;

std::cout << "\n=== 无符号和大整数类型 ===" << std::endl;
std::cout << "Unsigned: " << unsignedNum << std::endl;
std::cout << "Large Number: " << largeNumber << std::endl;

// 固定宽度整数类型 (C++11+)
int8_t smallInt = -128;
uint8_t unsignedSmallInt = 255;
int16_t mediumInt = 32767;
uint16_t unsignedMediumInt = 65535;
int32_t normalInt = -2147483648;
uint32_t unsignedNormalInt = 4294967295;
int64_t bigInt = LLONG_MIN;
uint64_t unsignedBigInt = ULLONG_MAX;


std::cout << "\n=== 固定宽度整数类型 ===" << std::endl;
std::cout << "int8_t: " << static_cast<int>(smallInt) << std::endl;
std::cout << "uint8_t: " << static_cast<int>(unsignedSmallInt) << std::endl;
std::cout << "int16_t: " << mediumInt << std::endl;
std::cout << "uint16_t: " << unsignedMediumInt << std::endl;
std::cout << "int32_t: " << normalInt << std::endl;
std::cout << "uint32_t: " << unsignedNormalInt << std::endl;
std::cout << "int64_t: " << bigInt << std::endl;
std::cout << "uint64_t: " << unsignedBigInt << std::endl;

// 常量
const int MAX_VALUE = 100;
constexpr double PI = 3.14159265359;

std::cout << "\n=== 常量 ===" << std::endl;
std::cout << "MAX_VALUE: " << MAX_VALUE << std::endl;
std::cout << "PI: " << PI << std::endl;

// 类型转换
std::cout << "\n=== 类型转换 ===" << std::endl;
int integer = 100;
double floating = 3.14;

// 隐式类型转换
double result1 = integer + floating;
std::cout << "Implicit conversion (int to double): " << result1 << std::endl;

// 显式类型转换
int result2 = static_cast<int>(floating);
std::cout << "Explicit conversion (double to int): " << result2 << std::endl;

// C风格类型转换
int result3 = (int)floating;
std::cout << "C-style conversion (double to int): " << result3 << std::endl;

// 变量的作用域
std::cout << "\n=== 变量的作用域 ===" << std::endl;
int globalLike = 10;
{
int local = 20;
std::cout << "Local variable: " << local << std::endl;
std::cout << "Global-like variable inside block: " << globalLike << std::endl;
}
std::cout << "Global-like variable outside block: " << globalLike << std::endl;

// 变量的初始化
std::cout << "\n=== 变量的初始化 ===" << std::endl;
int a = 1; // 拷贝初始化
int b(2); // 直接初始化
int c{3}; // 列表初始化 (C++11+)
int d = {4}; // 拷贝列表初始化 (C++11+)
int e{}; // 值初始化 (C++11+)

std::cout << "a: " << a << std::endl;
std::cout << "b: " << b << std::endl;
std::cout << "c: " << c << std::endl;
std::cout << "d: " << d << std::endl;
std::cout << "e: " << e << std::endl;

// 类型别名
std::cout << "\n=== 类型别名 ===" << std::endl;
typedef unsigned long ulong;
using uint = unsigned int;

ulong number1 = 123456789;
uint number2 = 987654321;

std::cout << "typedef unsigned long: " << number1 << std::endl;
std::cout << "using unsigned int: " << number2 << std::endl;

// 字符串类型
std::cout << "\n=== 字符串类型 ===" << std::endl;
char cString[] = "Hello C-style string";
std::string cppString = "Hello C++ string";

std::cout << "C-style string: " << cString << std::endl;
std::cout << "C++ string: " << cppString << std::endl;
std::cout << "C++ string length: " << cppString.length() << std::endl;

return 0;
}