指针

摘要:

指针由两部分构成,1.目标变量的类型 2.指针类型:如 int *

定义指针时要求必须和该指针所指向变量类型相致

在32位计算机中无论指针(指针变量简称指针)指向的是何种变量,所有指针在内存中占4个字节。

在使用指针前必须给指针赋值;同数据类型的指针可以互相赋值

指针变量只能存放已定义变量的地址,不能直接给制止变量赋予整数或任何地址,不能通过输入得到地址

* 两种不同含义,具体看使用语境,一种为指针说明符;另一种是间接运算符或指针运算符或去内容运算符,若P为指针变量,*p则为P所指向的目标变量

int a = 5;

int *p = &a;

则*p和a等效 其值都是5.

&p 表示指针变量P本身的地址

指针赋值:

int a;
int *p;
p=&a;

或者

int a;
int *p = &a;
指针运算:

1. 对指针赋值

int *p = &a;

2. 地址运算“&”和内容运算“*”,这两个互为逆运算

int a =5;
int *p=&a;
则&(*p)=&a
   *(&a)=a

3. 加减

int a[] = "1,2,3,4,5"
int p=&a;
则*p=1
*p++=2;
*(p+2)=3;
*(p+3)=4;
指针加n或减n表示指针由当前所指向的位置向后或向前移动n个数据元素位置

移动后的实际地址为:p±n*sizeof(数据类型) 注意字节编址对齐

*p++相当于*(p++);

4. 比较

指针不能和一般数值进行比较但是可以和0和NULL进行比较

(指向)整型指针:

先看如下示例:

 #include <iostream>
 using namespace std;
  
 int main()
 {
     int a = 5;
     int * p = &a;
     cout << "a  = " <<  a << endl
          << "&a = " << &a << endl 
          << "*p = " << *p << endl 
          << "p  = " << p << endl 
          << "&p = " << &p << endl;
 
     return 0;
 }

运行结果如下:

指针

我们先看下内存分配图:

指针

由上图可以清楚的知道,输出整形变量a的值是5,指针变量p的值是001BFD18,而*号的作用是取值,*p即取地址001BFD18中存放的值,即5。

(指向)字符型指针:

可以使用字符数组和字符指针代表一个字符串

字符数组只有在定义时才能一起赋值,程序中对字符数组只能对各元素赋值,对字符串指针可以直接赋值字符串。

先看如下示例:

 #include <iostream>
 using namespace std;
 
 int main()
 {
     char a[] = "hello";
     char *p = a;
 
     cout << "p = " << p << endl
          <<"p = " << (void *) p << endl
          << "*p = " << *p << endl;
         
         
     for(int i = 0 ; i < 5; i++)
     {
         cout << "&a[" << i << "] = "<< (voi*)&a[i] << endl;
     }
     return 0;
 }

运行结果图如下:

指针

为什么整型指针p输出的是地址,而字符型指针输出的是字符串呢,字符型指针里存放的不是地址吗?

我们先看下内存分配图:

指针

由上图可以看出,其实p中存放的是地址,只是当cout时,如果指针是字符型指针,那么会输出p中地址指向的内存中的内容(这里是h)直到遇到'\0'才结束。所以直接输出p时会输出hello,而将p强制转换为void *时输出的是地址。

指针与数组:数组指针

一个数组名实际就是个指针常量,不是指针变量,不能给数组名赋值。数组名的值即编译器给数组分配的数组起始地址

数组名代表数组的第一个元素的地址.

当指针变量指向一维数组的第一个元素,指针变量名就可以当成一维数组名使用。也可以通过指针移动访问数组元素 p=a或者p=&a[0]

访问一个数组元素可以使用:

1. 下标法 a[i];(数组名的下标变量访问)

2.指针法*(p+i);(指针+偏移量的间接地址访问)

3.*(a+i);(数组名作为地址值得直接地址访问)

4.p[i]; (指针作为数组名的下标变量访问)

指针数组:一个数组中每个元素都是指针

如 char *a[]={"hello",

               "well",};

指针与结构数组:结构指针

strcut info{
short a;
int b[6];
};
strcut info myinfo, *pinfo;
pinfo =&myinfo;

则可以用指针访问结构成员:

1.通过结构变量名访问 myinfo.a

2. 通过指针间接运算符访问 (*pinfo).a

3. 通过指针和成员运算符访问 pinfo->a

函数指针:
int (*p)(int a ,int b);
p=max;
这里p实际上指向函数指针变量,其指向函数具有两int类型参数并且函数返回int类型数据
我们使用此指针来调用函数int c=p(10 ,5);
其实此时p变量也是存的地址,此地址即该函数入口地址,pint *类型变量进行函数调用

指针强转:
char a='A';
char *p=&a;
int *p1=(int *)p; //p强制转换指向整型数据指针
cout<<*p1<<endl; // 输出'A'ASCII码值65

指向指针的指针:

在说指向指针的指针之前,不得不说指向变量的指针。先看如下示例:

 指向整型指针的指针

先看如下示例:

 #include <iostream>
 using namespace std;
 
 int main()
 {
     int a[5] = {1, 2, 3, 4, 5};
     int *p = a;
     int **point = &p;
 
     cout << "a = " << a << endl
         << "p = " << p << endl
         << "&p = " << &p << endl
         << "point = " << point << endl
         << "&point = " << &point << endl;
 
     for (int i = 0; i < 5; i++)
     {
         cout << "&a[" << i << "] = " << &a] << endl;
     }
     return 0;
 }


运行结果图如下:
指针

我们先看下内存分配图:

指针

从上图可以看出point指针中存放的是p指针的地址,而p指针中存放的是a[0]的地址。所以*point和p是一样的,前者是取point指针中存放的地址(0025F754)中的值,即取地址0025F754中存放的值(0025F760),而后者就是0025F760,所以两者是等价的。**point和a[0]是等价的,前者可以写成*p,*p是取p中存放的地址(0025F760)中的值,即地址0025F760中存放的值1。由上可以得出*point等于p, **point 等于 a[0]。通过上图可以清晰的对付诸如*point++等问题。

4. 指向字符型指针的指针

先看如下示例:

#include <iostream>
using namespace std;
 
int main()
{
    char *a[] = {"Wel", "To", "China"};
    char **p = a;
    for(int i = 0; i < 3; i++)
    {
        for (int j = 0; j < strlen(a[i]) + 1; j++)
        {
            cout << a[i][j] << "\t" << (void *)&a[i][j] << endl;
        }
        cout << endl;
    }
    
    for (int i = 0; i < 3; i++)
    {
        cout << "a[" << i << "] = " << (void**) a[i] << endl
             << "&a[" << i << "] = " << &a[i] << endl;
    } 


    cout << "p  = " << p << endl
         << "&p = " << &p << endl;
    return 0;
}

运行结果图如下:

指针

我们先看下内存分配图:

指针

由上图可以看出a[0]中存放着'W'的地址,a[1]中存放着'T'的地址,a[2]中存放着'C'的地址,只是这些地址都是指向字符型的,所以直接cout的会输出字符串,而指针p中存放着a[0]的地址,所以*p等于a[0],都是获得'W'的地址,即00A778CCC,而**p和a[0][0]等价都获得了地址00A778CCC中存放的值W。由上图我们可以看到字符地址相隔1个字节,而指针地址相隔4个字节,这样就便于++运算,获得下一个地址了,列如++p后,p就指向a[1],p中存放的是a[1]的地址。

 


;