c++ 指针和数组

本章主要介绍c++常用的指针,包括基本类型指针,数组指针,函数指针,数组指针等。

                             常用的数组,包括基本类型数组,函数数组,指针数组等。

1.基本类型指针

如:int* s;//该指针表示只向一个int型数据的指针,内存里存放的是某个int型数据的地址,(任何指针类型在32位系统中占4个字节)

int a; //a在栈里存放

       s=&a;//s里存放的是变量a的地址

   基本类型数组

       如:int b[7];//b表示一个装有7个int数据元素的数组,定义数组时,明确数组的长度

数组名表示的是数组首元素地址,也就是上面,b,&b,&b[0]的值是一样的。虽然值是一样的,但是表达的意思还是不同,b(数组名)和&b[0]表示的意思一样,都表示数组首元素的地址,而&b表示的是该数组的地址。

int* t = b;

int *t1 = &b[0];

//这两种写法都正确,因为数组首元素是int类型,用指向int型的指针是正确的。

int* er = &b;//错误的,因为&b表示的是数组的地址,本例中应该用指向装有7个int型数据元素的数组指针才对。

int (* tr)[7];//定义一个指向装有7个int型元素数组的指针。(下面详细讲解)

tr = &b;//正确。

2.数组指针

如上例的:int (*tr)[7]; //这里定义的一个数组指针,指向的装有7个Int型元素数组的指针

理解方式:都知道int p[7]; p表示一个装有7个元素的数组,这里int (*tr)[7],用*tr替换p,*tr表示一个装有7个元素的数组,则tr表示的就是一个装有7个int型元素数组的指针。

指针数组(即存放指针的数组)

如: int* s[10];//这是一个简单的指针数组,s表示一个存放10个int型指针的数组。

理解方式:[](下标运算符)的优先级高于*运算符,s[10]表示存放10个元素的数组,*号表示存放的数据类型是否是指针。

注意:指针移动如,int* p;p+1;指针加1,并不是意味指针移动一个字节,指针移动是按照指针所指向的数据类型所占字节为单位进行移动,这里的p指针指向的是int类型数据,p+1表示移动1个int类型个字节,因此是4个字节。

3.函数指针

如: int (*p)(int a,int b)   //定义一个函数指针p,用于指向一个带两个int型参数,且返回值是int型的函数

int add(int a,int b)

{

return a+b;

}

p = add;     //正确赋值,函数名实际上就是函数地址

p(3,4);     //正确调用

   一般我们会用typedef int (*p)(int a,int b)  声明一个函数指针类型

p s;   //s表示的就是一个指向带两个Int型参数且返回值是Int型数据的函数

 函数指针数组

如: int (*p[2])(int a,int b);  //表示函数指针数组,p表示存放2个函数指针的的数组,且函数指针是指向带两个Int型参数且返回值是Int型数据的函数;

理解方式:都知道int (*)(int a,int b)声明带两个int型参数返回值是Int型数据的函数指针类型,而[]运算符的优先级高于*,int (*p[2])(int a,int b);p表示存有两个函数指针的数组.

 指向函数指针数组的指针

如:int (* (*p)[2])(int a,int b) ;  //p表示指向存有2个函数指针的数组。

理解方式:()优先级高,*p看成一个整体t,则int (* t[2])(int a,int b);t表示的是函数指针数组,所以p表示指向函数指针的数组

 

注意: 指针是针对内存的,指针的加减实际上是以指针所指类型为单位进行加减的

下面着重说明函数指针与指向类成员函数指针
我们经常接触的函数指针定义或声明函数指针类型时时,只注意:
1.函数返回值
2.函数参数(形参)个数以及参数类型
实际上函数指针的定义和声明要注意的应该有三点:
1.函数返回值
2.函数参数(形参)个数和参数类型
3.函数所属类类型。

一、指向不属于某个类里的函数指针

普通函数指针的定义 int (*fun)(int,int);
一般我们说:函数指针fun指向一个返回值类型为int,且带两个形参为int型的函数。
其实这么说是不准确的,准确来说,函数指针fun指向一个不属于某个类里、返回值类型为int型,带两个形参
分别为int,int型的函数。
赋值如:
int add(int a,int b)
{
return a+b;
}
fun = add;//正确,普通函数名表示函数的地址。
fun = &add;//正确
使用函数指针:fun(5,6);//正确
     (*fun)(5,6);//正确

二、指向类的成员函数的指针
指向类成员函数的函数指针有两种情况:
1.指向类里非静态成员函数
2.指向类里静态成员函数

注意:这里说的成员函数均是用public修饰的,只有用public修饰的成员才能在类外使用。
1)指向类里非静态成员函数的函数指针的声明和定义,如:

void ttt()

{}

class A
{
public:
int fun(char,int);

static void (*p)();
static int sfun(char,int);
};

void (*A::p)()=ttt;//正确,void (*A::p)()表示给class A里的static 成员p赋值。注意void(A::*p)()这个表示的是一个指向类A里的无参数无返回值得成员函数。


int A::fun(char,int)
{
printf("class::\n");
return 0;
}
int A::sfun(char,int)
{
printf("static\n");
return 0;
}

typedef int(A::*q)(char,int); //声明一个指向A类里,返回值为int型,带两个形参
,类型分别是char,int型的函数指针类型。可以通过自定义的类型,定义变量,如:
q h=&A::fun; //正确
int (A::*P)(char,int);//定义一个函数指针,指向A类里,返回值为int型,带两个形参
,类型分别是char,int型的函数。

2)指向类里非静态成员函数的赋值,如(使用上面的p指针):
p = &A::fun; //这里和指向不属于类里的函数指针有区别,记住,要获取类里的非静
态成员函数的地址必须通过类才能获得,同样,要想使用类里的非静态成员函数,必须通过类实例化的
对象才可以。
注意:这里说的成员函数指的是非静态的成员函数。

3)使用指向类里非静态成员函数的指针,如(使用商密看的p指针):
因为p是指向A(类)里的fun方法的,所以需要用类实例化的对象才能调用p;
A a;
(a.*p)('c',5); //正确,注意这里(a.*p)的括号不能少。*p才是a的成员函数。
或者A * a=new A();
(a->*p)('c',6); //正确。

4)指向类里静态成员函数的函数指针的声明和定义,如:
因为静态成员函数是属于类的,不属于某个具体对象。他和全局函数一样放在静态存储区
里,所以声明时,不能用类名限定(反而用类名限定还编译出错)
typedef int(*k)(char,int); //正确;可以看出,指向静态成员函数的函数指针声
明与指向不属于某个类里的函数声明一样。

int (*j)(char,int); //定义一个函数指针j,该指针既能指向不属于类里的函数,也
能指向属于类里的静态成员函数,但是函数的返回值是int型,带两个参数,类型分别为
char、int。

5)指向类里静态成员的函数指针的赋值,如:
j=A::sfun; //正确;
j=&A::sfun; //正确;这里也可以看出,指向类里静态成员函数的函数指针赋值和指
向不属于类里的函数指针赋值一样,都有两种方式,不过指向类里的需要用类名::限定。

6)指向类里静态成员函数的使用,如(使用上面的j指针):
j('c',9); // 正确;调用方式与指向不属于类里的函数指针一样,直接使用。
(*j)('c',9);//也正确;

A::j('c',9);//错误,类A里没有j成员函数。

这里着重说一下const指针和非const指针赋值问题:
在c++里,在指针或指针引用赋值时,只能缩小权限,不能扩大权限。
如:
    int i;
    int* t1 = &i;
    const int* t2 = &i;//可以将非const指针类型赋值给const指针类型,缩小权限。
    t1 = t2;//error ?将const指针类型赋值给非const指针类型错误,扩大权限,编译出错。
    const int* & t3 = &i;
    int* &t4=&i;
    t4=t3;//错误,同上
在c++里,有两种方式可以去掉变量的const:
一、使用强转
    t1=(int*)t2;//可以
二、使用const_cast操作符
    t1 = const_cast<int*>(t2);//正确
    char s[]="abcd";//这里的s实际上时char* const 类型,始终指向数组首元素的地址。不能s++。但是可以*s='d';   
















 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值