前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OC学习3——C语言特性之指针

OC学习3——C语言特性之指针

作者头像
mukekeheart
发布2018-02-27 16:07:20
1.4K0
发布2018-02-27 16:07:20
举报
文章被收录于专栏:mukekeheart的iOS之旅

1、指针是C语言中的一个非常重要的概念,实际上,OC系统类的变量、自定义类的变量等都是指针。定义指针变量的语法格式如下,其中*代表一个指针变量,整个语法代表定义一个指向特定类型的变量的指针变量。注意:指针变量不能保存普通的数值,它只能保存指针(也就是变量或对象的地址)。函数的形参传递方式有值传递和地址传递两种,其中地址传递就是传递的指针。

代码语言:javascript
复制
类型* 变量名 ;

float* ft ;
int* a ;

2、关于指针,还有两个最基本的运算符,取地址运算符(&)和取变量运算符(*)。

&:取地址运算符,单目运算符,后面通常紧跟一个变量,该运算符用于读取该变量所在的内存地址。

*:取变量运算符,单目运算符,后面通常紧跟一个指针变量,该运算符用于读取该指针变量所指向的内存中的变量。

3、数组变量的本质就说指针常量,该指针常量指向第一个数组元素。下面两种赋值方式的本质是一样的,而且大部分时候都会采用第二种方式来获取数组的首地址。所以,将数组变量作为参数传递到函数中实际上是一种地址传递。

代码语言:javascript
复制
int arr[5] = {1, 2, 3, 4, 5} ;

int* p1 = &arr[0] ;  //将第一个数组元素的地址赋值给指针变量p1
int* p2 = arr ;  //将数组变量保存的地址赋值给指针变量p2

需要指出的是,虽然数组变量保存的是数组第一个元素的地址,但是数组中保存的地址是不能改变的,因此,数组变量应称为指针常量。所以,执行arr++,arr += 2这种语句都是试图对arr数组变量进行重新赋值,这都是错误的

4、指向多维数组的指针变量,例如int arr[3][4] ;实际上是相当于定义了如下的三个数组变量:

arr[0]:该数组中再次包含了arr[0][0]、arr[0][1]、arr[0][2]、arr[0][3]四个元素,其中arr[0]表示指向arr[0][0]元素的地址的指针变量。

arr[1]:该数组中再次包含了arr[1][0]、arr[1][1]、arr[1][2]、arr[1][3]四个元素,其中arr[1]表示指向arr[1][0]元素的地址的指针变量。

arr[2]:该数组中再次包含了arr[2][0]、arr[2][1]、arr[2][2]、arr[2][3]四个元素,其中arr[2]表示指向arr[2][0]元素的地址的指针变量。

注意,arr[1][2]与 *(arr[1]+2) 、*(*(arr+1)+2)表示的意义是一样的,都是表示取arr[1][2]的值

5、指针的运算除了取地址、取变量和赋值之外,还有一些其他的运算需要注意,具体介绍如下:

指针变量加(减)一个整数:当指针变量加或减n时,代表将该指针的地址加或减n*变量大小个字节。举例来说,对于int* p;类型的变量,假如当前p变量中保存的地址为0x00010004,p+2则代表的地址是0x0001000C,因为一个int类型的数据占据4个四节,所以p+2实际上是往后移两个int类型的数据,相当于移8个字节。而对于char* p1;类型,若p1保存的地址是0x00020003,则p1+4则表示的地址是0x00020007。

当两个指针变量指向同一个数组的元素时,两个指针变量可以相减:两个指针变量相减,返回两个指针所指数组之间元素的个数。如果两个指针不指向同一个数组的元素,那么这两个指针变量相减没有任何意义。

当两个指针变量指向同一个数组的元素时,两个指针变量可以比较大小:指向前面的数组元素的指针小于指向后面的数组元素的指针。需要指出的是,如果两个指针不指向同一个数组的元素,那么这两个指针变量比较大小没有任何意义。

6、C语言的底层没有对字符串进行定义,一般都是通过字符数组进行保存字符串。此外,还可以通过字符指针来表示字符串,即定义一个字符指针变量,然后将C格式的字符串赋给该指针变量。

代码语言:javascript
复制
char* str = "I love IOS" ;

C语言的自字符串在底层依然是才用字符数组进行保存的,而str则是一个char*型的指针变量,它指向该字符数组的第一个元素,也就是指向该字符数组的首地址。

7、指针变量除了可以指向普通的int变量、float变量和数组之外,还可以指向函数的入口。当定义函数之后,C语言允许定义一个指针变量来指向该函数,然后就可以通过该指针变量来调用函数了,使用函数指针变量的语法格式步骤如下:

  1. 定义函数指针变量:函数返回值类型 (*指针变量名)();
  2. 将任何已有的函数赋值给函数指针变量:指针变量名 = 函数名 ; 
  3. 使用函数指针变量来调用函数:(*函数指针变量名)(参数);
代码语言:javascript
复制
 1 #import <Foundation/Foundation.h>
 2 
 3 int max(int * data, int len)
 4 {
 5     int max = *data ;
 6     //采用指针遍历data数组的元素
 7     for(int *p = data; p < data+len; p++)
 8     {
 9         //保证max始终存储较大的值
10         if(*p > max)
11         {
12             max = *p ;
13          }
14     }
15     return max ;
16 }
17 
18 int main(int argc, char* argv[])
19 {
20     int data[] = {1,2,3,4};
21     //定义函数指针变量fnPt,并将max函数赋值给fnPt
22     int (*fnPt) () = max ;
23     //通过函数指针变量调用函数
24     NSLog(@"最大值 max = %d", (*fnPt) (data , 5)) ;
25 }

函数指针的主要作用就是(1)把指针函数当作形参传递给某些具有一定通用功能的模块。并封装成接口来提高代码的灵活性和后期维护的便捷性;(2)有些地方必须使用函数函数指针才能完成给定的任务,如linux系统中的异步信号中断处理,当发生某一触发信号时,需要调用相应的处理函数,此时需要使用函数指针来实现。

代码语言:javascript
复制
void (*signal(int signum,void(* handler)(int)))(int);  

参数一为信号条件,第二个参数为一个函数指针,它所指向的函数需要一个整型参数,无返回值。该函数的返回值也是一个函数指针,返回的指针所指向的函数有一个整型参数(一般不用)

8、函数既可以返回普通的int、float等类型,也可以返回一个指针。但是当函数返回一个指针的时候需要注意,由于函数返回的指针只保存了一个地址值,如果该指针指向的是被调用函数中的局部变量,这就非常危险了,因为函数中的局部变量在函数调用结束之后会被自动释放,这样会导致该内存中所保存的数据是不确定的。所以,为哦了保证函数返回的指针是有效的,有三种方式:

  1. 如果函数返回的指针是指向函数中的局部变量,该局部变量应该使用static修饰。
  2. 让函数返回的指针指向暂时不会被释放的数据,如指向main()函数中的变量。
  3. 让函数返回的指针指向全局变量。

9、指针数组是值数组中的每个元素都是一个指针变量,常见的main()函数的形参第二个参数定义是char* argv[]就是一个指针数组。详情可以参见数组指针和指针数组的区别

代码语言:javascript
复制
 1 //指针数组的定义语法
 2 类型* 变量名[长度];
 3 
 4 char* arr[3] ;
 5 arr[0] = "hello world!";
 6 arr[1] = "I love IOS";
 7 arr[2] = "how are you ?";
 8 
 9 //注意区分上面的指针数组与下面的区别
10 类型 (*变量名)[长度];
11 
12 //第二种写法中(*变量名)先形成一个整体,代表一个指针变量,该指针指向一位数组,因此表示定义一个指向一位数组的指针变量
13 int a[3][4];
14 int (*p)[4];  //该语句是定义一个数组指针,指向含4个元素的一维数组。
15 p=a;           //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
16 p++;          //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

 10、指向指针变量的指针:也称指针的指针。指针变量也是变量,也需要保存在内存中,因此指针变量也有自己的存储地址,如果再次定一个一个指针变量来保存这个地址,则这个指针变量就说指向指针变量的指针。

代码语言:javascript
复制
类型** 变量名;
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-08-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档