目录
  1. 1. C++指针
    1. 1.1. 什么是指针
    2. 1.2. C++中使用指针
    3. 1.3. C++指针详解
      1. 1.3.0.0.1. C++ NULL指针:
        1. 1.3.0.0.1.1. C++指针的算术运算
        2. 1.3.0.0.1.2. 递增一个指针
        3. 1.3.0.0.1.3. 递减一个指针
        4. 1.3.0.0.1.4. 指针的比较
      2. 1.3.0.0.2. C++ 指针VS数组
C++指针

C++指针

每一个变量都有一个内存位置,每一个内存位置都可使用连字号(&)运算符访问地址,它表示了在内存中的一个地址。一下实例将输出定义的变量地址:

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

using namespace std;

int main()
{
int var1;
char var[20];

cout<<"var1 变量地址:";
cout<< &var1 << endl;

cout<<"var2 变量地址:";
cout<< &var2 << endl;

return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

1
2
var1 变量的地址:0xbfebd5c0
var2 变量的地址: 0xbfebd5b6

以上实例我们了解了什么是内存地址以及如何访问它。接下来让我们看一下什么是指针。

什么是指针

指针是一个变量,其值为另一个变量的地址,即内存位置的直接地址。就像其他变量或常量一样,必须使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式:

1
type *var-name

在这里,type是指针的基类型,它必须是一个有效的C++数据类型,var-name是指针变量的名称。用来声明指针的星号*与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来制定一个变量是指针。以下是有效的指针声明:

1
2
3
4
int    *ip; /* 一个整型的指针*/
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch; /* 一个字符型的指针 */

所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的的变量或常量的数据类型不同。

C++中使用指针

使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值。这些是通过使用一元运算符*来返回位于操作数所指定地址的变量的值。下面实例涉及到了这些操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>

using namespace std;

int main()
{
int var = 20;//实际变量声明
int *ip;//指针变量声明

ip = &var;// 在指针变量中存储var的地址

cout << " Value of var variable:";
cout << var << endl;

//输出在指针变量中存储的地址
cout << "Address stored in ip variable:";
cout << ip << endl;

//访问指针中地址的值
cout << "Value of *ip variable:";
cout << *ip << endl;

return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

1
2
3
Value of var variable: 20
Address stored in ip variable: 0xbfc601ac
Value of *ip variable: 20

C++指针详解

C++ NULL指针:

在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个NULL值是一个良好的编程习惯。赋为NULL值的指针被称为空指针。

NULL指针是一个定义在标准库中的值为零的常量。下面程序:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

using namespace std;

int main()
{
int *ptr = NULL;

cout << "ptr的值是"<< ptr;

return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

1
ptr 的值是 0

在大多数的操作系统上,程序不允许访问地址为0的内存,因为该内存是操作系统保留的。然而,内存地址0有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含控制(零值),则假定它不指向任何东西。
如需检查一个空指针,您可以使用 if 语句,如下所示:

1
2
if(ptr)     /* 如果 ptr 非空,则完成 */
if(!ptr) /* 如果 ptr 为空,则完成 */

因此,如果所有未使用的指针都被赋予空值,同时避免使用空指针,就可以防止误用一个未初始化的指针。很多时候,未初始化的变量存有一些垃圾值,导致程序难以调试。

C++指针的算术运算

指针是一个用数值表示的地址。因此,可以对指针执行算术运算。可以对指针进行四种算术运算:++、 –、 +、 -。

假设ptr是一个指向地址1000的整型指针,是一个32位的整数,让外卖对该指针执行下列的算术运算:

1
ptr++

在执行完上述运算之后,ptr将指向1004,因为ptr每增加一次,它都将指向下一个整数位置,即当前位置往后移4个字节。这个运算会在不影响内存位置中实际值的情况下,移动指针到下一个内存位置。如果ptr指向一个地址为1000的字符,上面的运算会导致指针指向位置1001,因为下一个字符位置是在1001.

递增一个指针

我们喜欢在程序中使用指针代替数组。因为变量指针可以递增,而数组不能递增,因为数组是一个常量指针。下面的程序递增变量指针,以便顺序访问数组中的每一个元素:

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
#include <iostream>

using namespace std;
const int MAX = 3;

int main()
{
int var[MAX] = {10, 100, 200};
int *ptr;

//指针中的数组地址
ptr = var;
for (int i = 0; i < MAx; i++)
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;

cout << "Value of var[" << i << "] =";
cout << *ptr <,endl;

//移动到下一个位置
ptr++;
}
return 0;
}

当上面的代码被编译和运行时,它会产生下列结果:

1
2
3
4
5
6
Address of var[0] = 0xbfa088b0
Value of var[0] = 10
Address of var[1] = 0xbfa088b4
Value of var[1] = 100
Address of var[2] = 0xbfa088b8
Value of var[2] = 200
递减一个指针

同样的,对指针进行递减运算,即把值减去其数据类型的字节数,如下所示:

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
#include <iostream>

using namespace std;
const int MAX = 3;

int main()
{
int var[MAX] = {10, 100, 200};
int *ptr;

//指针中最后一个元素的地址
ptr = &var[MAX -1];
for (int i = MAX; i > 0; i--)
{
cout << "Address of var[" << i <<"] = ";
cout << ptr << endl;

cout << "Value of var[" << i << "] =";
cout << *ptr << endl;

//移动到下一个位置
ptr--;
}
return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

1
2
3
4
5
6
Address of var[3] = 0xbfdb70f8
Value of var[3] = 200
Address of var[2] = 0xbfdb70f4
Value of var[2] = 100
Address of var[1] = 0xbfdb70f0
Value of var[1] = 10
指针的比较

指针可以用关系运算符进行比较,如==、<和>。如果p1和p2指向两个相关的变量,比如同一个数组中的补贴元素,则可对p1和p2进行大小比较。

下面的程序修改了上面的实例,只要变量指针所指向的地址小于或等于数组的最后一个元素的地址&var[MAX - 1], 则把变量指针进行递增:

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
#include <iostream>

using namespace std;
const int MAX = 3;

int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;

// 指针中第一个元素的地址
ptr = var;
int i = 0;
while ( ptr <= &var[MAX - 1] )
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;

cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;

// 指向上一个位置
ptr++;
i++;
}
return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

1
2
3
4
5
6
Address of var[0] = 0xbfce42d0
Value of var[0] = 10
Address of var[1] = 0xbfce42d4
Value of var[1] = 100
Address of var[2] = 0xbfce42d8
Value of var[2] = 200
C++ 指针VS数组

指针和数组是密切相关的。事实上,指针和数组在很多情况下是可以互换的。例如,一个指向数组开头的指针,可以通过使用指针的算术运算或数组索引来访问数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include  <iostream>

using namespace std;
const int MAX = 3;

int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;

//ptr = var;
for (int i = 0; i < MAX; i++)
{
cout << "var[" << i << "]的内存地址为";
cout << ptr << endl;

cout << "var[" << i << "]的值为";
cout << *ptr << endl;

//移动到下一个位置
ptr++;
}
return 0;
}
文章作者: XyLan
文章链接: https://blog.xylan.cn/2023/04/26/C++%E6%8C%87%E9%92%88/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 XyLan
打赏
  • 微信
  • 支付寶