前方一大波指针正在赶来~

原创 2016年05月30日 13:34:59

我们知道,通常我们来访问数组元素和指针变量的时候都可以通过下标和偏移两种方式来访问,那么他们有什么不一样的地方呢?

wKioL1ZijAuQEKFXAABLi_GPCH0242.png

我们来看一个小栗子:

int main ( )
{
             int a [5] = { 1, 2 , 3, 4, 5 };
             int *ptr = (int *)(& a + 1 );
             printf( "%d %d\n" ,*(a+ 1),*(ptr -1));
             system("pause" );
             return 0 ;
}

##对指针进行的加一操作实际上加的是指针类型的大小而不是以字节为单位。

&a+1:取出数组的首地址,在该地址上面加上一个sizeof(a)的值,即&a+5*sizeof(int)

 a+1:数组第二个元素的地址

二维数组

int arr[i][j]  访问方式:*(*(arr+i)+j)       

int main ( )
{
             int arr [3][ 2] = { (0 , 1), ( 2, 3 ), (4, 5) };
             int  *p ;
             p = arr [0];
             printf( "%d" , p[ 0] );
             system("pause" );
             return 0 ;
}

结果:1

详解:在数组中我们用括号将元素包含在其中,我们认为它是逗号表达式,在数组初始化的时候之初始化逗号表达式里最后一个元素。所以arr[0][0]=1  

         上述程序中p=a[0]相当于p=&a[0][0]。 

int main ( )
{
             int a [5][ 5];
             int( *p )[4];
             p = (int (*)[4]) a;
             printf( "%p ,%d\n" , &p[ 4][2 ] - &a[ 4][2 ], &p[ 4][2 ] - &a[ 4][2 ] );
             system("pause" );
             return 0 ;
}

结果: FFFFFFFc  -4

详解:我们使用一个大小为4的数组指针来访问了一个大小为5 的数组,在p的眼中默认它的数组大小是4,所以每次它的外层下标加一被默认为越过了4个元素,

          而a的外层下标加一被默认为是越过了5个元素

int main ( )
{
             int aa [2][ 5] = { 1 , 2, 3, 4 , 5, 6, 7 , 8, 9, 0 };
             int *ptr1 = (int *)(& aa + 1 );
             int *ptr2 =/*(int *)*/(*( aa + 1 ));
             printf( "%d%d" , *(ptr1 - 1), *(ptr2 - 1) );
             system("pause" );
             return 0 ;
}

结果:10 5

详解:&aa+1指向0后面的元素,强转成int之后-1则向前偏移一个整形空间

          (aa+1) 其中aa表示一维数组的首址,aa的类型是int(*)[5]加一之后偏移五个整形空间指向6,再解引用相当于&aa[1][0]向前偏移一个字节空间指向5

二级指针:存放以及指针变量的地址

一维数组的传参

函数声明为int fun(int *p)

数组 int arr[10]的传参形式可以为: 1.fun(arr)  2.fun(&arr[])

二维数组传参

1.将其作为一维数组处理将首元素首址传参

int fun ( int * p )
int main( )
{
             int arr [3][ 4];
             fun( &arr [0][ 0] );
}

2.将指针指向整个内层一维数组传参

int fun ( int( * p )[4 ] )
int main( )
{
             int arr [3][ 4];
             fun( arr );
}

##在函数内部不能使用sizeof 来求数组的大小,所以必须传参获得数组的大小

利用二级指针的传参

当利用二级指针传参时,我们要将一级指针的地址传入

函数被声明为:int fun2(int **p){...} 我们在传参时可以这样传:fun2(&p) /*p为一个指针变量 */      fun2(&arr)   /*  arr被声明为char *arr[] ,其是一个指针数组  */

典型错误:内存泄漏 ,str开辟内存失败

原因:形参是实参的临时拷贝,对于指针变量也是同样,我们在平时使用的传址调用的成功实现是因为我们通过解引用访问了指针变量存放的地址的内容,而在这里,我们是直接对指针变量进行操作,我们所分配的空间都给了局部变量st而不是我们所期望的str

void getmemory ( char * st )
{
             st = (char *)malloc( 20 * sizepf( char ) );
             if (st == NULL)
            {
                         printf( "Out of memory!\n" );
                         exit( EXIT_FAILUR )
            }
}
int main ( )
{
             char *str = NULL;
             getmemory( &str );
             return 0 ;
}

改正:传进指针的地址即二级指针

void getmemory ( char ** st )
{
            * st = (char *)malloc( 20 * sizepf( char ) );
             if (*st == NULL)
            {
                         printf( "Out of memory!\n" );
                         exit( EXIT_FAILUR )
            }
}
int main ( )
{
             char *str = NULL;
             getmemory( &str );
             return 0 ;
}

典型错误:返回局部变量地址

char *getmemory ( )
{
             char arr [10];
             return arr ;
}
int main ( )
{
             char *str ;
             str = get memory( );
            strcpy( str, "abc" );
             return 0 ;
}

改正:将临时变量改成静态变量,空间不被销毁可以访问

char *getmemory ( )
{
             static char arr[ 10];
             return arr ;
}
int main ( )
{
             char *str ;
             str = get memory( );
            strcpy( str, "abc" );
             return 0 ;
}

函数指针

测试输出函数的地址:

printf( "&fun = %p\n" , &fun );

printf( "fun = %p\n" , fun );

输出结果相同

##在函数指针中fun和&fun没有任何区别,完全相同

调用函数:

fun( );

(*fun)();

(************fun)();

程序结果相同------*符号在此没有作用,编译器不识别!

函数的地址要保存在一个指针中

函数指针的书写形式:一般来说我们根据函数的类型来书写指针 【类型】【指针名】【函数的参数类型列表】

EG:   通过函数指针来访问函数

int add ( int a, int b ){ ... };
int main ( )
{
             int( *padd )(int, int) = add ;
             int ret = (*padd)( 1, 2 );
             return 0 ;
}

引入函数指针的意义:实现回调函数

int add ( int a, int b )
{
             return a + b;
}
int sub ( int a, int b )
{
             return a - b;
}
int operation ( int( * pfun )(int , int) )
{
             int num1 = 0;
             int num2 = 0;
             scanf( num1 , num2 );
             return pfun ( num1, num2 );
}
int main ( )
{
             int ret operation( add );
             printf( "%d\n" , ret );
             system( "pause" );
             return 0 ;
}

函数指针数组

int( *pfun [4] )( char *, const char *);
pfun[0 ] = fun;
pfun[1 ] = fun1;

调用:pfun[i]("123","123");

本文出自 “Zimomo” 博客,请务必保留此出处http://zimomo.blog.51cto.com/10799874/1719857

版权声明:本文为博主原创文章,未经博主允许不得转载。

一大波线下培训机构正在倒闭。。。在线一对一辅导的春天来了!

线下培训机构倒闭,纷纷卷款逃跑,直接影响的就是那些一次交半年一年学费的家长们!在线一对一辅导、网络家教,妈妈再也不用担心我交的钱被卷跑了!来吧,1号教室,在线一对一辅导、网络家教平台欢迎你!http:...
  • avsuper
  • avsuper
  • 2013年11月08日 13:34
  • 2400

机器学习书籍一大波

  • 2017年11月07日 19:51
  • 48B
  • 下载

量化分析师的Python日记【第4天:一大波金融Library来袭之scipy篇】

上一篇介绍了numpy,本篇中着重介绍一下另一个量化金融中常用的库 scipy   一、SciPy概述 前篇已经大致介绍了NumPy,接下来让我们看看SciPy能...

一大波超级经典好看的英文字体

  • 2015年09月04日 09:30
  • 4.1MB
  • 下载

一大波设计用经典好看中文字体

  • 2015年09月04日 09:49
  • 42.11MB
  • 下载

量化分析师的Python日记【第4天:一大波金融Library来袭之scipy篇】

####一、SciPy概述 前篇已经大致介绍了NumPy,接下来让我们看看SciPy能做些什么。NumPy替我们搞定了向量和矩阵的相关操作,基本上算是一个高级的科学计算器。SciPy基于NumP...

大波霸炒股机

  • 2013年02月04日 06:01
  • 7.8MB
  • 下载

高通推双摄像头模块, 一大波手机厂商高兴坏了

摄像头如今曾经成为了智妙手机最主要的设置装备摆设之一,而往年特别盛行双摄像头的设置装备摆设,就连苹果这种颇为“顽固”的公司都为iPhone 7 Plus参加了双摄像头。分歧平日来说,摄像头不会自力任务...
  • m_mm123
  • m_mm123
  • 2016年09月16日 21:01
  • 193

一大波Deep Learning的实际应用

微软Skype已经能够实时的将语音翻译为多种语言,几乎就和星际迷航里的那款是一样一样滴。 http://blogs.skype.com/2014/12/15/skype-translator-how-...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:前方一大波指针正在赶来~
举报原因:
原因补充:

(最多只允许输入30个字)