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

类型* 变量名 ;

float* ft ;
int* a ;

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

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

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

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

int arr[] = {, , , , } ;

int* p1 = &arr[] ;  //将第一个数组元素的地址赋值给指针变量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格式的字符串赋给该指针变量。

char* str = "I love IOS" ;

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

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

  1. 定义函数指针变量:函数返回值类型 (*指针变量名)();
  2. 将任何已有的函数赋值给函数指针变量:指针变量名 = 函数名 ;
  3. 使用函数指针变量来调用函数:(*函数指针变量名)(参数);
 #import <Foundation/Foundation.h>

 int max(int * data, int len)
{
int max = *data ;
//采用指针遍历data数组的元素
for(int *p = data; p < data+len; p++)
{
//保证max始终存储较大的值
if(*p > max)
{
max = *p ;
}
}
return max ;
} int main(int argc, char* argv[])
{
int data[] = {,,,};
//定义函数指针变量fnPt,并将max函数赋值给fnPt
int (*fnPt) () = max ;
//通过函数指针变量调用函数
NSLog(@"最大值 max = %d", (*fnPt) (data , )) ;
}

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

void (*signal(int signum,void(* handler)(int)))(int);  

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

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

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

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

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

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

类型** 变量名;

OC学习3——C语言特性之指针的更多相关文章

  1. OC学习2——C语言特性之函数

    1.OC是在C语言的基础上进行扩展的,在OC中直接用C语言进行coding也是可以通过编译的.因此,函数定义的语法格式如下: 函数返回值类型 函数名(形参列表) { //由零条或多条可执行性语句组成的 ...

  2. GO学习-(10) Go语言基础之指针

    Go语言基础之指针 区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针. 要搞明白Go语言中的指针需要先知道3个概念:指针地址.指针类型和指针取值. Go语言中的指针 任何程序数 ...

  3. ndk学习之C语言基础复习----指针、函数、预处理器

    指针: 指针乃C.C++的灵魂之所在,所以有必要好好的复习复习.什么是指针?一句话来概括:“指针是一个变量,它的值是一个地址.”,其中指针变量的声明有如下三种形式: 其中第一种是被推荐的写法. 其中还 ...

  4. 【转】浅思OC的语言特性

    算了算,学习IOS已经有一段时间了.今天花了点时间思考一下OC的语言特性,让自己的心不要那么浮躁,注重基础,回归本源. OC做为一门面向对象语言,自然具有面向对象的语言特性,如封装.继承.多态.他具有 ...

  5. 浅思OC的语言特性

    算了算,学习IOS已经有一段时间了.今天花了点时间思考一下OC的语言特性,让自己的心不要那么浮躁,注重基础,回归本源. OC做为一门面向对象语言,自然具有面向对象的语言特性,如封装.继承.多态.他具有 ...

  6. OC学习6——面相对象的三大特性

    我们在学习Java的时候都知道,类有三大特性:继承,封装,多态,这也是面向对象的三大特征.OC学习篇之---类的三大特性(封装,继承,多态) 1.封装(Encapsulation)是指将对象的状态信息 ...

  7. 学习小程序第三天 WXML语言特性

    WXML语言特性     1.数据绑定   Musstache 语法 获取json中指定键值:变量名加双括号的绑定语法 如下: (1)绑定文本 注意所有组件和属性 都要小写 (2)绑定属性     ( ...

  8. OC学习5——类和对象

    1.OC是在C语言基础上进行扩展得到的一门面向对象的程序设计语言,它也提供了定义类.成员变量和方法的基本功能.类可以被认为是一种自定义的数据类型,使用它可以定义变量,所有使用类定义的变量都是指针类型的 ...

  9. (转载)OC学习篇之---第一个程序HelloWorld

    之前的一片文章简单的介绍了OC的相关概述,从这篇开始我们就开始学习OC的相关知识了,在学习之前,个人感觉需要了解的其他的两门语言:一个是C/C++,一个是面向对象的语言(当然C++就是面向对象,不过这 ...

随机推荐

  1. django + nginx + uwsgi

    server{ listen ; server_name 0.0.0.0; charset utf-; access_log /var/log/nginx/access.log main; locat ...

  2. Javascript的算法题目

    用js实现单链表的增删,直接上代码 const linkList=new LinkList() function LinkList(){ var Node=function(element){ thi ...

  3. 从汇编层面解释switch语句判断快速的原因

      源码如下: #include <stdio.h>   void main(){     int flag;     flag=1;     switch (flag){         ...

  4. PHP Laravel定时任务Schedule

    前提:本文方法是利用Linux的crontab定时任务来协助实现Laravel调度(Mac也一样). 一.首先添加Crontab定时任务,这里只做简单介绍. 用命令crontab -e 添加如下内容 ...

  5. [转贴]LTP--linux稳定性测试 linux性能测试 ltp压力测试 ---IBM 的 linux test project

    https://blog.csdn.net/melody157398/article/details/24354415   LTP--linux稳定性测试 linux性能测试 ltp压力测试 ---I ...

  6. python基础 (编码进阶,文件操作和深浅copy)

    1.编码的进阶 字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码. 即先将其他编码的字符串解码(decode)成unicode,再从uni ...

  7. linux下反弹shell

    01 前言 CTF中一些命令执行的题目需要反弹shell,于是solo一波. 02 环境 win10      192.168.43.151       监听端    装有nc kali        ...

  8. Java多线程系列4 线程交互(wait和notify方法)

    wait()/ notify()/ notifyAll() 任何Object对象都可以作为这三个方法的主调,但是不推荐线程对象调用这些方法. 1使用wait().notify()和notifyAll( ...

  9. java web+模板

    这次测试需要在java web的基础上套入模板,在测试的过程中我遇到了许多问题,现在我可以使用模板来美化网页的许多格式.但是模板的许多代码我还是看不懂,其中有jquery的许多代码.在今后我会学习相关 ...

  10. # 2019-2020-3 《Java 程序设计》第三周总结

    2019-2020-3 <Java 程序设计>第三周知识总结 1.类的定义 语法格式如下(加[]表示可选项): [修饰符] class 类名 { 属性定义(声明) 方法定义(声明)} 2. ...