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

原创 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

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

相关文章推荐

一大波Deep Learning的实际应用

微软Skype已经能够实时的将语音翻译为多种语言,几乎就和星际迷航里的那款是一样一样滴。 http://blogs.skype.com/2014/12/15/skype-translator-how-...

大波霸炒股机

  • 2013-02-04 06:01
  • 7.80MB
  • 下载

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

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

一大波AMD 300系列新显卡售价曝光

原文地址:http://www.sanerliu.com/showtopic-304.page 前两天,讯景自曝了R9 390X的非公零售版,紧接着微星也拿出了R9、R7 300系列的多款...

【NOI OJ】一大波题正在飞来(ˉ▽ ̄~) 我才不是 Ctrl C + Ctrl V 的人呢

OpenJudge 登入注册 管理员 frank  林舒  Dzx  someo...

手淘、微博、苹果、Twitter、Facebook一大波互联网巨头使用框架被泄露_Netty是什么神秘所在?

原文链接 手淘、微博一直钟情的 Netty框架是个什么鬼? 发布时间:2017-05-15 18:23:065614人关注77人参与 众所周知,构建高性能的现代互联网架构,我...

程序员证明自己智商的时候到了,一大波智力面试题正在靠近

与传统的面试不同,程序设计面试题以程序设计题、IQ智力题及各种与计算机相关的技术性问题为主。其中智力题,每个正式的笔试、面试都会出,而且在面大企业的时候必然会问到,下面介绍几个面试智力题。 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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