文章目录
【 1. 指针的定义 】 【 2. 指针的调用 】 【 3. NULL 空指针 】 【 4. 指针的算术运算 】 4.1 指针的递加 4.2 指针的递减 4.3 指针的比较
【 5. 指针与数组 】 5.1 通过指针操作数组 5.2 指针数组、数组指针
【 6. 指向指针的指针(多级间接寻址)】 【 7. 传递指针给函数 】 【 8. 函数返回指针 】
指针的作用 :通过指针,可以简化一些 C++ 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。内存和指针的关系 :每一个变量都有一个内存位置(理解为:每一个变量在内存中都占有一个位置 / 占用一定内存空间),每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。 内存位置相当于房间,地址相当于门牌号 。
【 1. 指针的定义 】
指针是一个变量,其值为另一个变量的地址 ,即,内存位置的直接地址。 不同数据类型的指针都是一个代表内存地址的长的十六进制数 。唯一的不同是,指针所指向的变量或常量的数据类型不同。指针变量声明的一般形式为:
type 是指针的基类型,它必须是一个有效的 C++ 数据类型; 用来声明指针的星号 * 与乘法中使用的星号是相同的,但在这个语句中,星号用来指定一个变量是指针; var-name 是指针变量的名称。
type * var- name;
int * ip;
double * dp;
float * fp;
char * ch;
【 2. 指针的调用 】
使用指针时会频繁进行以下几个操作:① 定义一个指针变量 、② 把变量地址赋值给指针 、③ 访问指针变量中可用地址的值 。这些是通过使用一元运算符 * 来返回位于操作数所指定地址的变量的值。
# include <iostream>
using namespace std;
int main ( )
{
int var = 20 ;
int * ip;
ip = & 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 ;
}
【 3. NULL 空指针 】
在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值(即指向地址为0的内存)是一个良好的编程习惯。赋为 NULL 值的指针被称为 空指针 。 NULL 指针是一个定义在标准库中的值为零的常量。 地址为0的内存 : 在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的 。然而 指向内存地址 0的NULL空指针表明该指针不指向一个可访问的内存位置 。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。实例:
# include <iostream>
using namespace std;
int main ( )
{
int * ptr = NULL ;
cout << "ptr 的值是 " << ptr ;
if 0
cout << "*ptr 的值是 " << * ptr ;
end
return 0 ;
}
if ( ptr)
if ( ! ptr)
NULL指针的意义 :很多时候,未初始化的变量存有一些垃圾值,导致程序难以调试。因此, 如果所有未使用的指针都被赋予空值,同时避免使用空指针,就可以 防止误用一个未初始化的指针 。
【 4. 指针的算术运算 】
指针的值表示地址,但归根到底还是一个变量。因此,我们可以对指针执行算术运算。 可以对指针进行四种算术运算:++、- -、+、-。 指针运算的基本单元 = 指针指向变量的数据类型所占字节大小 。
假设 ptr 是一个指向地址 1000 的整型指针,是一个 32 位的整数,我们对该指针执行下列的算术运算:ptr++; 在执行完上述的运算之后,ptr 将指向位置 1004,因为 ptr 每增加一次,它都将指向下一个整数位置,即当前位置往后移 4 个字节。这个运算会在不影响内存位置中实际值的情况下,移动指针到下一个内存位置。 如果 ptr 指向一个地址为 1000 的字符,上面的运算会导致指针指向位置 1001,因为下一个字符位置是在 1001。
4.1 指针的递加
实例:下面的程序递增变量指针,以便顺序访问数组中的每一个元素
# 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 ;
}
4.2 指针的递减
实例:下面的程序递减变量指针,以便顺序访问数组中的每一个元素。
# 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 ;
}
4.3 指针的比较
指针可以用关系运算符进行比较,如 ==、< 和 >。如果 p1 和 p2 指向两个相关的变量,比如同一个数组中的不同元素,则可对 p1 和 p2 进行大小比较。 下面的程序修改了上面的实例,只要变量指针所指向的地址小于或等于数组的最后一个元素的地址 &var[MAX - 1],则把变量指针进行递增:
# 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 ;
}
【 5. 指针与数组 】
5.1 通过指针操作数组
我们经常在程序中使用指针存储数组首元素的地址,即指针指向数组首元素。这是因为 指针作为一个变量可以递增,而 数组名本身就是一个常指针,不能赋值 。
# 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++ )
{
if ( 1 )
{
cout<< * ptr << endl;
ptr++ ;
}
else
{
cout<< * var << endl;
}
}
return 0 ;
}
* ( var + 2 ) = 500 ;
5.2 指针数组、数组指针
【 6. 指向指针的指针(多级间接寻址)】
指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时, 第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的地址 。 一个指向指针的指针变量必须如下声明,即 在变量名前放置两个星号 。如下声明了一个指向 int 类型指针的指针:
int * * var;
实例 :当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符:
# include <iostream>
using namespace std;
int main ( )
{
int var;
int * ptr;
int * * pptr;
var = 3000 ;
ptr = & var;
pptr = & ptr;
cout << "var 值为 :" << var << endl;
cout << "*ptr 值为:" << * ptr << endl;
cout << "**pptr 值为:" << * * pptr << endl;
return 0 ;
}
【 7. 传递指针给函数 】
C++ 允许我们传递指针给函数,只需简单地声明函数参数为指针类型即可。 指针作为函数形参时,若在函数内部改变了指针所指向变量的值,则调用完该函数后该变量的值也会变化 ,因为这是直接对指针所指向的内存地址中的数据进行操作的。实例
# include <iostream>
# include <ctime>
using namespace std;
void getSeconds ( unsigned long * par)
{
* par = time ( NULL ) ;
return ;
}
int main ( )
{
unsigned long sec;
getSeconds ( & sec ) ;
cout << "Number of seconds :" << sec << endl;
return 0 ;
}
# include <iostream>
using namespace std;
double getAverage ( int * arr, int size) ;
int main ( )
{
int balance[ 5 ] = { 1000 , 2 , 3 , 17 , 50 } ;
double avg;
avg = getAverage ( balance, 5 ) ;
cout << "Average value is: " << avg << endl;
return 0 ;
}
double getAverage ( int * arr, int size)
{
int i, sum = 0 ;
double avg;
for ( i = 0 ; i < size; ++ i)
{
sum += arr[ i] ;
}
avg = double ( sum) / size;
return avg;
}
【 8. 函数返回指针 】
int * myFunction ( )
{
. . .
}
C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量 。实例 :生成 10 个随机数,并使用表示指针的数组名(即第一个数组元素的地址)来返回它们,具体如下:
# include <iostream>
# include <ctime>
# include <cstdlib>
using namespace std;
int * getRandom ( )
{
static int r[ 10 ] ;
srand ( ( unsigned ) time ( NULL ) ) ;
for ( int i = 0 ; i < 10 ; ++ i)
{
r[ i] = rand ( ) ;
cout << r[ i] << endl;
}
return r;
}
int main ( )
{
int * p;
p = getRandom ( ) ;
for ( int i = 0 ; i < 10 ; i++ )
{
cout << "*(p + " << i << ") : " ;
cout << * ( p + i) << endl;
}
return 0 ;
}