c++函数参数或返回值为函数指针

=============================
int *p=NULL;
func(p);
void func(int *p)
{
p=(int *)malloc(sizeof(int)*10);
memset(p,0,sizeof(p));
p[0]=1;
}
===================================
int *ptr=NULL;
func(&ptr);
void func(int **p)
{
*p=(int *)malloc(sizeof(int)*10);
memset(*p,0,sizeof(*p));
*p[0]=1;
}
======================================

==================================================================================================================================================================

指针值为空作为函数参数传入

2018年05月19日 11:25:48 AmelieLiu 阅读数:809

下面以一个例子来引出这种错误:

 
  1. #include <iostream>

  2. using namespace std;

  3. #include <stdlib.h>

  4. #include <string.h>

  5. void func(int *p)

  6. {

  7. p = (int *)malloc(sizeof(int) * 10);

  8. memset(p, 0, sizeof(p));

  9. p[0] = 1;

  10. }

  11. int main()

  12. {

  13. int *p = NULL;

  14. func(p);

  15. cout << p[0] << endl;

  16. return 0;

  17. }

 

一个很简单的函数,就是给*p在函数中分配空间并将p[0]置成1,最后打印输出p[0]。但是运行的结果却是segmengt fault

我们通过查看这段程序的汇编代码来分析一下出现段错误的原因。

 
  1. Dump of assembler code for function func(int*):

  2. 0x00000000004008cd <+0>: push %rbp

  3. 0x00000000004008ce <+1>: mov %rsp,%rbp

  4. 0x00000000004008d1 <+4>: sub $0x20,%rsp

  5. 0x00000000004008d5 <+8>: mov %rdi,-0x18(%rbp)

  6. 0x00000000004008d9 <+12>: mov $0x28,%eax

  7. 0x00000000004008de <+17>: mov %rax,%rdi

  8. 0x00000000004008e1 <+20>: callq 0x400780 <malloc@plt>

  9. 0x00000000004008e6 <+25>: mov %rax,-0x8(%rbp)

  10. 0x00000000004008ea <+29>: mov -0x8(%rbp),%rax

  11. 0x00000000004008ee <+33>: mov $0x8,%edx

  12. 0x00000000004008f3 <+38>: mov $0x0,%esi

  13. 0x00000000004008f8 <+43>: mov %rax,%rdi

  14. 0x00000000004008fb <+46>: callq 0x400750 <memset@plt>

  15. 0x0000000000400900 <+51>: mov -0x8(%rbp),%rax

  16. 0x0000000000400904 <+55>: movl $0x1,(%rax)

  17. 0x000000000040090a <+61>: leaveq

  18. 0x000000000040090b <+62>: retq

  19. End of assembler dump.

 

重点放在

 
  1. sub $0x20,%rbp

  2. mov %rdi,-0x18(%rbp)

 

这两句汇编代码上。

sub $0x20,%rbp的意思是给栈分配0x20大小的空间。

mov %rdi,-0x18(%rbp)的意思是把函数的第一个参数的值压入栈中存储。 
这说明了什么?说明了函数中的*p其实是一个临时变量,和主函数并不是同一个*p了。给临时变量申请内存并赋值当前不能反映到主函数的*p上,所以主函数的*p还是个空指针,而打印空指针当然就段错误了。

下面介绍两种解决方法: 
1.函数返回临时指针的地址:

 
  1. #include <iostream>

  2. using namespace std;

  3. #include <stdlib.h>

  4. #include <string.h>

  5. int* func(int *p)

  6. {

  7. //此时的p是个临时指针

  8. p = (int *)malloc(sizeof(int) * 10);

  9. memset(p, 0, sizeof(p));

  10. p[0] = 1;

  11. return p; //返回地址

  12. }

  13. int main()

  14. {

  15. int *p = NULL;

  16. p = func(p);

  17. cout << p[0] << endl;

  18. return 0;

  19. }

 

2.传入指向指针的指针:

 
  1. #include <iostream>

  2. using namespace std;

  3. #include <stdlib.h>

  4. #include <string.h>

  5. //*p存储的是main函数*ptr的地址

  6. void func(int **p)

  7. {

  8. *p = (int *)malloc(sizeof(int) * 10);

  9. memset(*p, 0, sizeof(*p));

  10. *p[0] = 1;

  11. }

  12. int main()

  13. {

  14. int *ptr = NULL;

  15. func(&ptr);

  16. cout << ptr[0] << endl;

  17. return 0;

  18. }

 

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Move_now/article/details/71944689

文章标签: C指针传参陷阱临时变量

==================================================================================================================================================================

c++函数参数或返回值为函数指针

C++中函数指针的形式为:返回值类型 + 参数类型,函数没有值类型,但是却可以声明函数的指针,因为函数是可寻址的,存放在内存中的代码段,可以从指针访问。

函数指针可以声明为:

void (*pF)(void); 
//   ^括号1
//        ^括号2

其中pF为参数为空,返回值也为空的函数类型,因为*操作符的优先级低于函数调用操作符,所以必须在*pF外加括号。

那么如何声明返回值为函数指针的函数呢?

先给出一个实例:

void (* fun() )();
//   ^ 括号a  
//         ^括号b
//             ^括号c

该函数的返回值为一个函数指针,解析下这个声明的三个括号分别代表的意义:括号a对应第一个声明中的括号1,括号c对应第一个声明中的括号2,而括号c则是该函数自身的函数调用符,可以在该括号内放入函数参数如:

//参数为一个int类型
void (* fun(int x) )();
//参数为两个int类型
void (* fun(int x, int y) )();
//参数为一个函数指针类型
void (* fun( void (*f)() ) )();

其中第三个例子的参数为一个函数指针,括号比较多,要仔细看才能够看出这个声明的结构。

============================================================================================================================================================================================================================================================================

C++函数默认参数

2018年06月13日 09:20:09 luckydaxiang 阅读数:402

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/luckydaxiang/article/details/80673900

  对于带参数列表的函数,必须从右向左添加默认值。也就是说,要为某个参数设置默认值,则必须为它的右边的所有参数提供默认值:

 
  1. int function1(int n,int m = 4,int j = 5); //有效

  2. int function2(int n,int m = 6,int j); //无效

  3. int function3(int k = 1,int m = 2,int n = 3); //有效

例如,function1( )原型允许调用该函数时提供1个、2个或3个参数:

 
  1. beeps = function1(2);//即function1(2,4,5)

  2. beeps = function1(1,8);//即function1(1,8,5)

  3. beeps = function1(8,7,6);//即function1(8,7,6)没有使用默认参数

实参按从左到右的顺序依次被赋给相应的形参,而不能跳过任何参数。因此,下面的调用是不允许的:

beeps = function1(3,,8)//无效

猜你喜欢

转载自blog.csdn.net/lusic01/article/details/88193816