什么是指针?
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:
type *var-name;
type 是指针的基类型,它必须是一个有效的 数据类型,var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。以下是有效的指针声明:
int *ip; /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch; /* 一个字符型的指针 */
所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。
介绍一些基本概念。
1、Null指针:NULL 指针是一个定义在标准库中的值为零的常量。
NULL 指针是一个定义在标准库中的值为零的常量。
例子:
#include <iostream>
using namespace std;
int main ()
{
int *ptr = NULL;
cout << "ptr 的值是 " << ptr ;
return 0;
}
运行结果:
ptr 的值是 0
需要注意的是:
- 1、如需检查一个空指针,可以使用 if 语句
if(ptr) /* 如果 ptr 非空,则完成 */
if(!ptr) /* 如果 ptr 为空,则完成 */
- 2、如果所有未使用的指针都被赋予空值,同时避免使用空指针,就可以防止误用一个未初始化的指针。很多时候,未初始化的变量存有一些垃圾值,导致程序难以调试。
2、指针的算术运算:指针是一个用数值表示的地址。因此,您可以对指针执行算术运算。可以对指针进行四种算术运算:++、–、+、-。
只需注意:
2.1.指针指向数组的时候,不可以加 &
2.2. 指针指向数组中某一元素时要用 &
例子:
short int height[10]; //int型的数组(short int 每个数据2字节)
cout << "height "<< height << endl
<< "height+1 "<< height + 1 << endl
<< "&height[0] " << &height[0] << endl
<< "&height+1 "<< &height + 1<< endl
<< "height+9 "<< height+9 << endl
<< "height+10 " << height + 10 << endl;
运行结果:
height 0136F900
height+1 0136F902
&height[0] 0136F900
&height+1 0136F914
height+9 0136F912
height+10 0136F914
结论:
height 与 &height[0] 值相等。
height+1 = height + 2 字节 = height + 1 个 short int 也即 一个数组元素。
height+9 为 height[] 中最后一个元素的地址,height+10 为该数组结束后的第一个地址。
&height +1=height+10,即执行 &height+1 的结果是地址跳到整个数组之后第一个地址。
3、指针和数组之间的关系
指针和数组在很多情况下是可以互换的。例如,一个指向数组开头的指针,可以通过使用指针的算术运算或数组索引来访问数组。
然而,指针和数组并不是完全互换的。
例子:
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
for (int i = 0; i < MAX; i++)
{
*var = i; // 这是正确的语法
var++; // 这是不正确的
}
return 0;
}
把指针运算符 * 应用到 var 上是完全可以的,但修改 var 的值是非法的。这是因为 var 是一个指向数组开头的常量,不能作为左值。
由于一个数组名对应一个指针常量,只要不改变数组的值,仍然可以用指针形式的表达式。
例:*(var + 2) = 500;
4、指针数组:
一个指向整数的指针数组的声明:
int *ptr[MAX];//把 ptr 声明为一个数组,由 MAX 个整数指针组成。因此,ptr 中的每个元素,都是一个指向 int 值的指针
例1:
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr[MAX];
for (int i = 0; i < MAX; i++)
{
ptr[i] = &var[i]; // 赋值为整数的地址
}
for (int i = 0; i < MAX; i++)
{
cout << "Value of var[" << i << "] = ";
cout << *ptr[i] << endl;
}
return 0;
}
运行结果:
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200
例2:
#include <iostream>
using namespace std;
const int MAX = 4;
int main() {
const char *names[MAX] = {
"Zara Ali",
"Hina Ali",
"Nuha Ali",
"Sara Ali",
};
for (int i = 0; i < MAX; i++) {
cout << " --- names[i] = " << names[i] << endl;
cout << " --- *names[i] = " << *names[i] << endl;
cout << endl;
cout << " --- (*names[i] + 1) = " << (*names[i] + 1) << endl;
cout << " --- (char)(*names[i] + 1) = " << (char)(*names[i] + 1) << endl;
cout << " ------------------------------------ " << endl << endl << endl << endl;
}
return 0;
}
运行结果:
--- names[i] = Zara Ali
--- *names[i] = Z
--- (*names[i] + 1) = 91
--- (char)(*names[i] + 1) = [
------------------------------------
--- names[i] = Hina Ali
--- *names[i] = H
--- (*names[i] + 1) = 73
--- (char)(*names[i] + 1) = I
------------------------------------
--- names[i] = Nuha Ali
--- *names[i] = N
--- (*names[i] + 1) = 79
--- (char)(*names[i] + 1) = O
------------------------------------
--- names[i] = Sara Ali
--- *names[i] = S
--- (*names[i] + 1) = 84
--- (char)(*names[i] + 1) = T
------------------------------------
注意:
*char names[MAX] 是指针数组, 它的本质是存储指针的数组, 既存储 char 类型的指针的数组, 数组内的每个元素都是一个指针指向一个存储 char 类型的地址:
区分指针数组(int *ptr[3] )和数组指针(int (*ptr)[3])。
5、指向指针的指针(多级间接寻址)
指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
下面声明了一个指向 int 类型指针的指针:int **var;
当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符:
例:
#include <iostream>
using namespace std;
int main ()
{
int var;
int *ptr;
int **pptr;
var = 3000;
ptr = &var; // 获取 var 的地址
pptr = &ptr; // 使用运算符 & 获取 ptr 的地址
// 使用 pptr 获取值
cout << "var 值为 :" << var << endl;
cout << "*ptr 值为:" << *ptr << endl;
cout << "**pptr 值为:" << **pptr << endl;
cout << "var 地址为 :" << &var << endl;
cout << "ptr=&var 值为var的地址:" << ptr << endl;
cout << "ptr地址为:" << &ptr << endl;
cout << "*pptr=ptr=&var 值为var的地址:" << *pptr << endl;
cout << "pptr 地址为:" << &pptr << endl;
return 0;
}
运行结果:
var 值为 :3000
*ptr 值为:3000
**pptr 值为:3000
var 地址为 :0x7fffc1bc04ac
ptr=&var 值为var的地址:0x7fffc1bc04ac
ptr地址为:0x7fffc1bc04a0
*pptr=ptr=&var 值为var的地址:0x7fffc1bc04ac
pptr 地址为:0x7fffc1bc0498
6、传递指针给函数
例:
#include <iostream>
using namespace std;
// 函数声明
void getAverage(int *arr, int size,double *avg);
int main ()
{
int balance[5] = {1000, 2, 3, 17, 50}; // 带有 5 个元素的整型数组
double avg;
getAverage(balance, 5, &avg ) ; // 传递一个指向数组的指针作为参数
cout << "Average value is: " << avg << endl; // 输出返回值
return 0;
}
void getAverage(int *arr, int size,double *avg) //再次运用函数,使得sum得以累加
{
int i, sum = 0;
for (i = 0; i < size; ++i)
{
sum += arr[i];
}
*avg = double(sum) / size; //求平均
}
运行结果:
Average value is: 214.4
7、从函数返回指针
参见:https://blog.csdn.net/ouzhiqi9007/article/details/107134427