个性化阅读
专注于IT技术分析

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

上一章Objective-C开发教程请查看:Objective-C数组用法介绍

相对于C++中的引用,Objective-C的指针还是比较好的,而且在OC中编程推荐使用指针,因为使用指针更快。指针是用来动态申请内存的,对于如何回收的问题,后面的章节会详细讲解。

由前面的章节我们可以知道,一个变量对应于一个内存区域,每个内存区域都有一个地址,可以使用&操作符获取变量对应内存区域的地址,打印内存地址使用格式符%x,如下面的例子:

#import <Foundation/Foundation.h>

int main () {
   int  var1;
   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 () {
   int  var = 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 () {
   int  var[] = {10, 100, 200};
   int  i, *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 () {
   int  var[] = {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 () {
   int  var[] = {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;
}

二级指针

指向指针的指针是多个间接指针或指针链的一种形式。通常,指针包含一个变量的地址。当我们定义一个指针时,第一个指针包含第二个指针的地址,第二个指针指向包含实际值的位置,如下所示。

指向指针的指针

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

int * * var;

当一个指向指针的指针间接指向一个目标值时,访问该值需要应用两次星号操作符,如下例所示:

#import <Foundation/Foundation.h>
 
int main () {
   int  var;
   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;
}

@end

int main () {
   int sec;

   SampleClass *sampleClass = [[SampleClass alloc]init];
   [sampleClass getSeconds:&sec];

   NSLog(@"seconds: %d\n", sec );

   return 0;
}

函数返回指针

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

int * myFunction() {
.
.
.
}

要记住的第二点是,将局部变量的地址返回给函数外部不是一个好主意,因此必须将局部变量定义为静态变量。

现在,考虑下面的函数,它将生成10个随机数并使用数组名返回它们,数组名表示一个指针,即第一个数组元素的地址。

#import <Foundation/Foundation.h>

int * getRandom( ) {
   static int  r[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;
}
赞(0)
未经允许不得转载:srcmini » Objective-C指针解释和用法详解 – Objective-C开发教程

评论 抢沙发

评论前必须登录!