黑马程序员-两种容易混淆的指针及构造方法的执行过程分析

来源:互联网 发布:怎样在淘宝上买罂粟壳 编辑:程序博客网 时间:2024/05/16 09:13

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------


1.     函数指针与指针函数的区别:

int * f(int * p);

int (*f)(int * p);

第一个:

先找到变量名f,f()的优先级比*f的优先级高  所以f是个函数名,()中是这个函数的形参 int *p 去掉f()以及其中的形参 剩下的int * 就是该函数的 返回值 于是第一个就是一个返回值是int指针的函数简称指针函数

第二个:

找到变量名f,因为()的原因  f先和*结合,于是f就是个指针名,然后(*f)右边又有()说明这是个指向函数的指针,而这个函数的形参是*p 返回值就是去掉(*f)(int*p)剩下的 int

总结就是f是个指向形参为int型指针返回值为int型的函数的指针,简称函数指针。

更加复杂的声明也可以这样辨别。

比如float(*(*f)(int,int,int))(int);

1先找到变量名f  然后发现f先和*结合 说明f是个指针

2(*f)右边有个(int int int)说明f是个指向函数的指针 形参为3个int

3替换掉(*f)(int int int) 剩下的就是这个函数的返回值 float(*p)(int)

4 这个上面已经解释过是个指向形参int返回值float的函数的指针

5所以f是个函数指针 指向的函数形参为3个int 返回值还是个函数指针指针指向一个返回值float形参int的函数。

总之就是记号()[]的优先级相等从左往右结合,*的优先级是比()低一级的而*是从右往左结合然后声明是从变量名开始一层一层往外加,解读也是从变量名开始一层一层解读。无论是函数还是数组还是指针都很清楚了

2. 常量指针和指针常量的区别

1> 定义:

常量指针就是指针指向的是常量,它不能指向变量,它指向的内容不能被改变,不能通过指针来修改它指向的内容,但是指针自身不是常量,它自身的值可以改变,从而指向另一个常量。

    指针常量是指向的地址是不可改变的,但地址里的内容可以通过指针改变。它指向的地址将伴其一生,直到生命周期结束。有一点需要注意的是,指针常量在定义时必须同时赋初值。

2> 使用方法:

使用时写法上的区别: 常量指针:const 在*之前  指针常量:const在*之后。 当然我们也可以定义常量指针常量,那就需要加上两个const,一前一后!以上只是从定义上给出两者的本质上的不同,在具体使用上,还有很多变化,但万变不离其宗,我们可以根据它的原理分析出各种复杂用法的实质。

3> 使用举例

3.1 常量指针使用:如

int b,c; 

intconst *a; 

a =&b;

a =&c; 

都可以,唯独它指向的内存不能被修改。如:*a=20;这是违法的!错误!

3.2 指针常量使用如:

Int a;

IntaTest;

Int *const p = &a;

表示p是一个常量指针它指向变量a的内存。指针常量不能再用p指向

其他变量,如 p =& aTest; 错误!可以修改指向内存的值,如:* p =10;

3.3 使用技巧

使用指针常量可以增加代码的可靠性和执行效率。   

如 Int a;

Int *const p = &a;

增加可靠性:不用担心p被修改或释放导致非预期结果;

增加执行效率:不用在子函数中对p做为空检查可以提高效率。 

 

 

3. 用三种方法来交换两个整形变量的值。

1> 第一种方法,大家会借助第三个中间变量来实现:

int temp,a,b;

temp=a;

a=b;

b=temp;

这种方法需要借助第三变量来实现;思想:如果你两个手都拿着苹果,两手想要交换苹果,需要将一个苹果先放下,再交换。

2> 第二种方法是利用加减法实现两个变量的交换,

int a,b ;

    a=b-a;

b=b-a;

a=a+b;

思想:利用加法来进行两变量的交换,主要就是利用相加和相减,然后赋值,写法可以有多种。

3> 第三种方法是得用位异或运算来实现,也是效率最高的一种,在大量数据交换的时候,效率明显优于前两种方法,

int a,b;

a=a^b;

b=a^b;

a=a^b;

思想:利用一个数异或本身等于0和异或运算符合交换率。

 

4. 构造方法在执行的过程中内存分析:

1> Person*p = [ [Person alloc] init ];

Person先分配一块内存空间,由于Person继承的是NSOject,其父类中有isa成员变量,并且在初始化前,子类和父类的成员变量值都为0。然后调用init的构造方法(里面主要是对init父类方法的重写,完整的代码为 if( self = [super init] )),如果self分配成功,则对成员变量进行初始化(成员变量包括子类和继承过来的父类的)。

2> Student*s = [ [Student alloc] init];

  Student alloc是先给Student分配内存空间,然后初始化调用的是init方法是来自student的,就近原则,然后super找到person的init方法,而Person的 super init方法又要找到NSOject的,然后先对父类的成员变量赋值,再到子类。


0 0
原创粉丝点击