Objective-C指针解释和用法详解 – Objective-C开发教程

上一章Objective-C开发教程请查看:Objective-C数组用法介绍
相对于C++中的引用,Objective-C的指针还是比较好的,而且在OC中编程推荐使用指针,因为使用指针更快。指针是用来动态申请内存的,对于如何回收的问题,后面的章节会详细讲解。
由前面的章节我们可以知道,一个变量对应于一个内存区域,每个内存区域都有一个地址,可以使用& 操作符获取变量对应内存区域的地址,打印内存地址使用格式符%x,如下面的例子:

#import < Foundation/Foundation.h>int main () { intvar1; char var2[10]; NSLog(@"var1的地址: %x", & var1 ); NSLog(@"var2的地址: %x", & var2 ); return 0; }

什么是指针?一个指针是一个变量,我们可以做一个类比,整数类型的变量使用int声明,如int a; ,其中a是一个变量。那么指针其实也是一个类型,只不过不同数据类型有不同类型的指针。声明一个指针一定要带上类型,即使是void类型,语法如下:
type *pointer;

如上pointer就是一个type类型的指针,只能储存type类型的指针,它的值是一个地址,下面是更多的例子:
int *intPointer; double *doublePointer; char *charPointer; NSString *str;

再说一下,指针类型的变量的值是一个地址,这个地址是一个long类型的十六进制数,知道这个对你的编程也有帮助。long在mac中是8字节,也就是64位。
如何使用指针?首先我们需要定义一个指针变量,然后将变量的地址分配给这个指针变量,最后就可以使用该指针变量访问数据了。使用指针取值需要使用*操作符,下面是一个使用示例:
#import < Foundation/Foundation.h>int main () { intvar = 20; int*ip; ip = &var; NSLog(@"var变量的地址: %x", & var); NSLog(@"ip地址值: %x", ip ); NSLog(@"*ip的值: %d", *ip ); return 0; }

Objective-C中的NULL指针我们可以给指针初始化为NULL值,这样的指针称为空指针,NULL指针的值一般为0,下面是空指针的例子:
#import < Foundation/Foundation.h>int main () { int*ptr = NULL; NSLog(@"ptr的值 : %x", ptr); return 0; }

在大多数操作系统上,程序不允许访问地址0处的内存,因为该内存是由操作系统保留的。但是,内存地址0具有特殊的意义,它表示指针不打算指向可访问的内存位置。但是按照惯例,如果指针包含null(0)值,则假定它不指向任何东西。
要检查空指针,可以使用if语句,如下所示:
if(ptr)/* 如果ptr不是null则为true */ if(!ptr)/* 如果ptr是null则为true */

指针算术运算Objective-C指针是一个地址,它是一个数值。因此,可以对指针执行算术运算,就像可以对数值执行算术运算一样。指针上可以使用四种算术运算符:++、– 、+和-
为了理解指针算法,让我们考虑ptr是一个整数指针,它指向地址1000。假设32位整数,让我们对指针执行以下算术运算:
ptr++

现在,在上述操作之后,ptr将指向位置1004,因为每次ptr递增时,它将指向下一个整数位置,即当前位置旁边的4/8个字节。这个操作将把指针移动到下一个内存位置,而不会影响内存位置的实际值。如果ptr指向地址为1000的字符,那么上述操作将指向位置1001,因为下一个字符将在1001处可用。
递增一个指针
我们喜欢在程序中使用指针而不是数组,因为变量指针可以递增,不像数组名称不能递增,因为它是常量指针。下面的程序增加变量指针来访问数组的每个后续元素:
#import < Foundation/Foundation.h>const int MAX = 3; int main () { intvar[] = {10, 100, 200}; inti, *ptr; ptr = var; for ( i = 0; i < MAX; i++) { NSLog(@"var[%d]地址 = %x", i, ptr ); NSLog(@"var[%d] = %d", i, *ptr ); ptr++; } return 0; }

其它指针递减和比较的运算也是类似。
指针数组在我们理解指针数组的概念之前,让我们考虑一下下面的例子,它使用了一个有3个整数的数组:
#import < Foundation/Foundation.h> const int MAX = 3; int main () { intvar[] = {10, 100, 200}; int i; for (i = 0; i < MAX; i++) { NSLog(@"var[%d] = %d", i, var[i] ); } return 0; }

当我们想要维护一个数组时,可能会出现这样的情况,它可以存储指向int或char或任何其他可用数据类型的指针。下面是指向整数的指针数组的声明:
int *ptr[MAX];

这将ptr声明为一个最大整数指针数组。因此,ptr中的每个元素现在都有一个指向int值的指针。下面的例子使用了三个整数,它们将被存储在指针数组中,如下所示:
#import < Foundation/Foundation.h> const int MAX = 3; int main () { intvar[] = {10, 100, 200}; int i, *ptr[MAX]; for ( i = 0; i < MAX; i++) { ptr[i] = & var[i]; } for ( i = 0; i < MAX; i++) { NSLog(@"var[%d] = %d", i, *ptr[i] ); } return 0; }

二级指针指向指针的指针是多个间接指针或指针链的一种形式。通常,指针包含一个变量的地址。当我们定义一个指针时,第一个指针包含第二个指针的地址,第二个指针指向包含实际值的位置,如下所示。
Objective-C指针解释和用法详解 &#8211; Objective-C开发教程

文章图片
作为指针指针的变量必须这样声明。这是通过在它的名字前面加上一个星号来实现的。例如,下面是声明一个指向int -类型指针的声明:
int * * var;

当一个指向指针的指针间接指向一个目标值时,访问该值需要应用两次星号操作符,如下例所示:
#import < Foundation/Foundation.h> int main () { intvar; int*ptr; int**pptr; var = 3000; ptr = &var; pptr = &ptr; NSLog(@"var = %d", var ); NSLog(@"*ptr = %d", *ptr ); NSLog(@"**pptr = %d", **pptr); return 0; }

在Objective-C中传递指向函数的指针Objective-C编程语言允许你传递一个指向函数的指针。为此,只需将函数参数声明为指针类型。
下面是一个简单的例子,我们将一个无符号的长指针传递给一个函数,然后改变函数内部的值,这个值会在调用函数中得到反映:
#import < Foundation/Foundation.h> @interface SampleClass:NSObject - (void) getSeconds:(int *)par; @end@implementation SampleClass- (void) getSeconds:(int *)par { *par = time( NULL ); return; }@endint main () { int sec; SampleClass *sampleClass = [[SampleClass alloc]init]; [sampleClass getSeconds:& sec]; NSLog(@"seconds: %d\n", sec ); return 0; }

函数返回指针正如我们在上一章中看到的,Objective-C编程语言允许从函数中返回数组,类似的,Objective-C允许从函数中返回指针。为此,必须声明一个返回指针的函数,如下面的示例所示
int * myFunction() { . . . }

要记住的第二点是,将局部变量的地址返回给函数外部不是一个好主意,因此必须将局部变量定义为静态变量。
【Objective-C指针解释和用法详解 – Objective-C开发教程】现在,考虑下面的函数,它将生成10个随机数并使用数组名返回它们,数组名表示一个指针,即第一个数组元素的地址。
#import < Foundation/Foundation.h>int * getRandom( ) { static intr[10]; int i; srand( (unsigned)time( NULL ) ); for ( i = 0; i < 10; ++i) { r[i] = rand(); NSLog(@"%d", r[i] ); } return r; } int main () { int *p; int i; p = getRandom(); for ( i = 0; i < 10; i++ ) { NSLog(@"*(p + [%d]) : %d\n", i, *(p + i) ); } return 0; }

    推荐阅读