精华内容
下载资源
问答
  • c++指针作为函数参数传递的问题

    万次阅读 多人点赞 2018-09-30 11:23:51
      原创文章,转载请注明出处,谢谢! 作者:清林,博客名:飞空静渡 ...其实,对于C 或者C++ ,最难的一块地方估计就是指针了。指针是强大的,但也是很多人载在这里的地方。   前段时间写了一篇文章《...

    转自:http://blog.csdn.net/fjb2080/article/details/5623427

     

    原创文章,转载请注明出处,谢谢!
    作者:清林,博客名:飞空静渡

     

    博客地址:http://blog.csdn.net/fjb2080

     

    其实,对于C 或者C++ ,最难的一块地方估计就是指针了。指针是强大的,但也是很多人载在这里的地方。

     

    前段时间写了一篇文章《C ++之 数组与指针的异同 》对C 和C ++中的指针做了一个初步的讲解。这次将讲解一下指针作为函数参数传递的问题。

     

    很多人对于指针的使用是有所了解的,但还是经常会载在指针的问题上,是因为还不够了解指针的本质,其实如果了解指针的本质,对指针的使用也就一目了然了。

     

    作为C 的初学者,经常会遇到指针作为函数参数传递的两个经典的问题。这里,我将透过指针的本质来来讲解这两个问题,这样以后无论你遇到什么样的指针问题,如果你以这样的方法来分析指针也许就迎刃而解了!

     

    首先,第一个问题是这样的:

    写一个函数,交换两个参数中的值。

     

    初学者往往会这样写:

     

    void exchange(int x, int y)

    {

    int p=x;

    x = y;

    y = p;

    }

     

    之后,你会查找资料了解到应该这样写:

    void exchange(int *x, int *y)

    {

    int *p=x;

    *x = *y;

    *y = *p;

    }

     

    第二个问题是,写一个给某个指针分配内存的函数:

    初学者往往是这样写:

    void my_malloc(void* p, int size)

    {

    p = malloc(sizeof(int)*size);

    }

     

    然后又查在资料,知道应该这么写:

    void my_malloc(void** p, int size)

    {

    *p = malloc(sizeof(int)*size);

    }

     

    虽然,网上很多这样的讨论,也有很多人做过很多的解释,但始终都无法给出一个令人一目了然,并可以长久记住的说法,这篇文章就是想试图解决这样的问题,给初学者一个原理性的了解!

     

    首先,一定一定记住一点, 指针和变量一样,也是有地址的,只不过变量的值被解释成一个值,而指针的值被解释成一个地址。

     

    下面,我们看一下代码:

    void main()

    {

    int x;

    int *p;

    }

     

    我们看这个函数的内存结构:

     

    这是一个函数的栈结构,我们可以看到,变量和指针都占用了4 个字节。而且,由于我们对它们没有初始化,所以变量x 和指针p 里的内容都是随机的,就是说x 的值是不确定的,p 有可能指向某个内存地址,如果现在对p 操作也许会导致程序崩溃。

     

    其实,我们记住了,指针也是有地址的 这个概念,很多问题就迎刃而解了。

     

    下面,我来分析一下,指针作为函数参数传递的情况。

    如果,我们的代码是这样的,你看会怎么样:

     

    int main(int argc, char* argv[])

    {

    int *a = new int(10);

    func(a);

     

    return 0;

    }

     

    第一个要说的当然是:指针也是有地址的。

    第二个要说的是:当给一个函数的参数传递一个变量是,这个变量是复制过去的。

     

    对于第二点,我们在理解void exchange(int x, int y) 函数想交换这两个变量的的值时就应该理解了。

    例如:

    int a;

    int b;

    exchange(a,b);

    不能交换a 和b 的值,因为此时exchange(a,b) 中的a 和b 并不是原来的a 和b 变量,它们只不过是被复制过去了。

     

    有了这两个概念,就不难理解指针作为函数参数传递的问题。

     

    首先,我们来看下上面的代码中的a 指针和p 指针的内存结构。

    我们看到,当我们以a 作为func 函数的参数传递进去的时候,函数复制了这个指针,但这两个指针的内容是一样的,也就是说是指向同一个内存,即10 。

     

    如果你还不了解的话,我就通过一段代码和测试再来说明:

     

     

    [cpp] view plain copy

     print?

    1. #include <stdio.h>  
    2. void func(int* p)  
    3. {  
    4.     printf("*p = %d/n", *p);  
    5.     printf("&p = %p/n", &p);  
    6. }  
    7. int main(int argc, char *argv[])  
    8. {  
    9.     int *a = new int(10);  
    10.     printf("*a = %d/n", *a);  
    11.     printf("&a = %p/n", &a);  
    12.     func(a);  
    13.     return 0;  
    14. }  

     

     

     

    编译:g++ -g -Wall test1.cpp

    运行:./a.out

    输出:

    *a = 10

    &a = 0xbfd4447c

    *p = 10

    &p = 0xbfd44460

     

    我们看到输出,a 指向的地址的值和p 指向的地址里的值是一样的,都是10 。然而,对于指针a 和p 来说,它们自身的地址是不一样的,所以我们看到,函数func 复制了指针a 给p ,它们的值一样,但有不同的地址,是不同的指针。

     

    我们再进一步:

     

    [cpp] view plain copy

     print?

    1. #include <stdio.h>  
    2. void func(int* p)  
    3. {  
    4.     printf("*p = %d/n", *p);  
    5.     printf("&p = %p/n", &p);  
    6.     printf("&*p = %p/n", &*p);  
    7. }  
    8. int main(int argc, char *argv[])  
    9. {  
    10.     int *a = new int(10);  
    11.     printf("*a = %d/n", *a);  
    12.     printf("&a = %p/n", &a);  
    13.     printf("&*a = %p/n", &*a);  
    14.     func(a);  
    15.     return 0;  
    16. }  

     

     

     

    编译输出:

    *a = 10

    &a = 0xbfe1c77c

    &*a = 0x94b6008

    *p = 10

    &p = 0xbfe1c760

    &*p = 0x94b6008

     

    我们可以进一步看到,a 指针所指向的值的地址和p 指针所指向的值的地址是一样的,都是 0x94b6008 ,就如同上图所示,为了加深印象,再看一下这个图 ,然后再对比一下程序输出 ,然后在体会一下我在上面提到的两点 ,一点是:指针是有地址的 。另一点是:函数的参数是复制过去的 。

     

     

     

    说到这里,我们再回到文章开始时提到的两个问题,一个是交换问题:

     

    void exchange(int *x, int *y)

    {

    int *p=x;

    *x = *y;

    *y = *p;

    }

     

    那么这样为什么可以交换:

    int a = 2;

    int b = 3;

    exchange(&a, &b);

     

    上我们以a 和b 的地址传递给exchange 函数时,函数复制了这两个地址,并赋值给x 和y 这个两个指针,这两个指针是指向变量a 和b 的,它们的图形如下:

     

    那么,当我们反引用指针时:

    int *p=x;

    *x = *y;

    *y = *p;

     

    我们操作的是a 和b 里面的变量的值,所以,我们交换a 和b 的值就成功了。

     

    我们再来看下第二个问题:

    void my_malloc(void* p, int size)

    {

    p = malloc(sizeof(int)*size);

    }

    当这样时:

    int *a;

    my_malloc(a, 10);

    为什么这个会失败!

     

    下面,我来分析一下:

    当我们调用my_malloc(a, 10); 函数,而函数还没执行到p = malloc(size); 语句时,情况是这样的:

     

    我们看到a 和p 的指针的值都是一样的,都是指向某个不确定的地址。

    这时,我们执行这个语句:

    p = malloc(sizeof(int)*size);

    我们把这个语句分开两部分来看,一个是先执行malloc(sizeof(int)*size) ,然后在执行赋值语句,把malloc(sizeof(int)*size) 的返回值付给p 。

    第一步:先执行malloc(sizeof(int)*size) ;(这里我们只考虑malloc 分配内存成功的情况)

     

    第二步:把执行malloc(sizeof(int)*size) 的返回值付给了p ,如下图:

     

    由上图,我们可以知道,这就是为什么,我们还是不能给a 分配地址的了。

     

    下面我们来分析这个:

    void my_malloc(void** p, int size)

    {

    *p = malloc(sizeof(int)*size);

    }

     

    int *a;

    my_malloc(&a , 10);

    这样执行,为什么会成功!

     

     

    我们看到,当执行函数

    my_malloc(void** p, int size);

    但还没有执行

    *p = malloc(sizeof(int)*size);

    语句时,它们的内存结构图如下所示:

     

    其实这里,我们可以把二维指针和一维指针当成和变量一样,也是有地址的。只不过它的解释不一样而已。

    变量:里面的值是一个数值。

    一维指针:里面的值是个地址,而这个地址里的值是个数值。

    二维指针:里面的值是个地址,而这个地址里的值也是个地址。

     

    那么,我看着图来解释p :

    p 里面是一个地址,这个地址是&a ,即是a 指针的地址值,而a 指针地址里面的值也是个地址,这个地址是指向一个不确定的地方,说得坳口,慢慢对比图来理解就会好了!

     

    执行malloc(size) 后的图如下:

     

    然后在执行赋值语句:

    *p = malloc(sizeof(int)*size);

    后,如下图所示:

     

    然后,我们就给指针a 分配内存成功了。

     

    本文的pdf下载地址:c++之指针作为函数参数传递的问题.pdf

    展开全文
  • 本文主要介绍在 C/C++ 编程语言中,指针变量作为函数参数的用法示例。 1 示例1 示例代码如下: #include <stdio.h> #include <stdlib.h> int main() { /* 函数声明 */ int swap(int *p1, int *...

    本文主要介绍在 C/C++ 编程语言中,指针变量作为函数参数的用法示例。

    1 示例1

    示例代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        /* 函数声明 */ 
        int swap(int *p1, int *p2);
        
        int a = 0;
        int b = 0;
        int i = 0;
        int *pointer_1 = NULL;
        int *pointer_2 = NULL;
        
        printf("please input a and b: ");
        scanf("%d %d", &a, &b);
        /* 交换前a和b的值 */
        printf("before swap: a=%d, b=%d\n", a, b);
        
        pointer_1 = &a;
        pointer_2 = &b;
        
        i = swap(pointer_1, pointer_2);
        /* 交换后a和b的值 */ 
        printf("after swap: a=%d, b=%d\n", a, b);
        
        system("pause");
        
        return 0;
    }
    
    /* 
    *  在此函数中实现指针变量的值的交换 
    */
    int swap(int *p1, int *p2)
    {
        int tmp = 0;
        
        tmp = *p1;
        *p1 = *p2;
        *p2 = tmp;
        
        return 0; 
    }

    上述代码运行结果如下:

    please input a and b: 11 33
    before swap: a=11, b=33
    after swap: a=33, b=11

    对于上述代码及其运行结果,说明如下:

    1. 指针作为函数参数时,实际上是将变量的地址传给函数;
    2. 需要注意:函数 swap 的形参的定义形式为“int *p1”;而调用该函数时,实参形式为指针(变量地址)“pointer_1”。
    3. 函数 swap 的作用是交换两个变量(a 和 b)的值,其实现方法是通过交换指针变量所指向的值(*p1 和 *p2),而并非交换指针变量自身值(p1 和 p2)。这是因为:函数参数传递的方式是“单向值传递”的“值传递”方式(指针变量作为函数参数也是遵循这一规则),形参值(p1 和 p2)的改变不能使实参的值(pointer_1 和 pointer_2)随之改变,即,受“单向值传递”约束的只是指针变量(pointer_1 和 pointer_2),而指针变量(pointer_1 和 pointer_2)所指向的值(a 和 b)并不受约束,因此,可以通过指针变量作为函数参数的方式,改变指针变量所指向的参数值;
    4. 函数的调用可以(而且只可以)得到一个返回值(即函数值),而运用指针变量作为函数参数,可以得到多个变化的值。

    2 示例2

    对于示例 1 中的 swap 函数的实现方法,给出有一个典型的错误示例,代码内容如下:

    /*
    * swap函数的错误示例 *
    */
    int swap_error(int *p1, int *p2)
    {
        int *tmp;
        
        *tmp = *p1;
        *p1 = *p2;
        *p2 = *tmp;
        
        return 0; 
    }

    上述代码在编译时不会报错,但运行时会直接导致程序崩溃。

    目前猜测此问题的原因:*tmp 是指针变量 tmp 所指向的变量,但 *tmp 中并无确定的值,因此 tmp 所指向的单元也是不可预见的。所以,对 *tmp 赋值有可能会对一个存储着重要数据的存储单元赋值,这样就会破坏系统的正常工作。

    备注:上面所述只是猜测,并未证实。后续可通过 GDB 调试等方式,进一步确认此问题原因。

    综上,建议如示例 1 那样,使用整型变量 tmp 作为临时变量来实现 *p1 和 *p2 的交换。

    展开全文
  • C++函数指针函数作为参数

    千次阅读 2020-02-19 18:27:34
    所指函数的返回类型 + 指针名 + 所指函数参数列表 double (*pf)(int);// 指针pf指向的函数, 输入参数为int,返回值为double const vector<int>* (*seq_ptr)(int);// 指针seq_ptr指向一个vector类型的指针 ...

    1.构成:
    所指函数的返回类型 + 指针名 + 所指函数的参数列表

    double (*pf)(int);// 指针pf指向的函数, 输入参数为int,返回值为double 
    
    const vector<int>* (*seq_ptr)(int);// 指针seq_ptr指向一个vector类型的指针
    

    2.使用方式:

    const vector<int> *pseq = seq_ptr(pos);//赋值调用
    const vector<int> *pseq =*seq_ptr)(pos);//推荐使用
    
    
    double y = (*pf)(5);//推荐使用
    double y = (pf)(5)
    

    实例:注意函数名就是指针,将指针作为参数传入即可

    #include <stdio.h>
    #include <time.h>
    #include <iostream>
    
    clock_t start, stop;
    
    double duration;
    
    double f1(int n, double a[], double x)
    {
    	int i;
    	double p = a[0];
    	for (i = 1; i <= n; i++)
    		p += (a[i] * pow(x, i));
    	return p;
    }
    double f2(int n, double a[], double x)
    {
    	int i;
    	double p = a[n];
    	for (i = n; i > 0; i--)
    		p += ( a[i-1]+x * p );
    	return p;
    }
    
    void get_duration(int n, double a[], double x,double(*funtion_ptr)(int n ,double a[],double x))
    {
    	start = clock();
    	
    	double p = (*funtion_ptr)(n, a, x);
    		
    	stop = clock();
    	duration = ((double)(stop - start) / CLK_TCK);
    
    	std::cout << "\n tick:" << (double)(stop - start) << "\n"
    		<< "second:" << duration << std::endl;
    }
    const int max = 10;
    double f1(int n, double a[], double x);
    double f2(int n, double a[], double x);
    
    int main()
    {	
    	int i;
    	double a[max];
    	for (i = 0; i < max; i++) 
    		a[i] = (double) i; // turn to double for next calculate	
    	get_duration(max - 1, a, 1.1, f1);//将f1(函数名即是指针)作为参数传入
    	system("pause");
    	return 0;
    }
    

    3.指针数组
    构建一个装有函数的列表,可以用数组的特性来循环或选择

    const vector<int>* fibon_seq(int size);
    const vector<int>* lucas_seq(int size);
    const vector<int>* square_seq(int size);//3种数列除了计算方法别的参数都相同
    
    //seq_array是个数组,内放函数指针
    const vector<int>* (*seq_array[])(int) = {fibon_seq,lucas_seq,square_seq}//用数组的特性来循环
    int seq_index = 0;
    while(next_seq==true)
    {
    	seq_ptr = seq_array[++seq_index];
    }
    
    展开全文
  • c++指针函数作为参数传参

    万次阅读 2017-06-09 10:06:10
    在这里我们可以将(*function)视为函数指针,直接将函数名称传进去,但是内部获取的是指针,而不是函数本身,所以不用担心这么做是把函数拷贝一份浪费了内存的空间。 网上有一些用typedof方法的实现,其实也...

    今天发现了一种写法,顺便记录一下。废话不多说,先看代码:

    #include <iostream>
    
    using namespace std;
    
    int addition(int x, int y){
        return x + y;
    }
    
    int subtraction(int x, int y){
        return x - y;
    }
    
    int operation(int x, int y, int (*function)(int, int)){
        return (*function)(x, y);
    }
    
    int main(){
        int answer = operation(1, 2, addition);
        cout << answer;
    
    }
    在这里我们可以将(*function)视为函数的指针,直接将函数名称传进去,但是内部获取的是指针,而不是函数本身,所以不用担心这么做是把函数拷贝一份浪费了内存的空间。

    网上有一些用typedof方法的实现,其实也可以,但是这种方法相对更加简洁一些。对了,上面的

    int answer = operation(1, 2, addition);

    addition也可以加上&,但其实都一样。编译器会自己读取地址。

    对了,我上次发的那个在线编译器只支持c++98,如果想要在线测试比较新的c++功能,比如c++11或者c++14,那么可以访问http://cpp.sh/ (国内的网站可能打开会慢一些)上次国内的那个网站连一个输入函数都实现不了,这个是可以输入的,所以功能上要比上次那个好很多,哈哈。

    展开全文
  • 文章摘自“微学苑”,微学苑主讲C、C++和Shell ... 指针函数中的使用也是十分广泛的。某些情况下,将指针作为函数的参数或函数的返回值会给我们带来方便。而某些情况下,我们又...指针作为参数 我们在上一章我们已
  • C++用指向函数指针作为函数参数

    千次阅读 2018-12-05 19:42:12
    示例: #include &lt;iostream&gt; using namespace std; int add(int x, int y){ return x + y; } int sub(int x, int y){ ...int operation(int x, int y, int(*function)(int, int)){ return func...
  • 今天在学习过程中,发现在C++使用对象作为函数参数进行传递时,实参向形参采用传值的方法进行传递,但是在函数中使用this指针,分别指向对象的数据成员,在子函数结束后返回main函数时,依然能够改变实参(对象)的...
  • C++中,通过多维数据的指针作为函数参数传递源程序
  • c++指针和引用作为函数参数传递时的区别

    千次阅读 多人点赞 2020-06-03 09:15:57
    之前写过c++之值传递、引用传递、指针传递,今天再单独区分一下指针和引用作为函数参数传递时的区别。 本文参考浅谈C++中指针和引用的区别 一、指针作为函数参数传递时 1、类似于值传递,传入函数指针只是原指针的...
  • 引用博文:...当指针作为函数参数传递时,在函数内部重新申请了一个新指针,与传入指针指向相同地址。在函数内部的操作只能针对指针指向的值。#include &lt;iostream&gt; using namespace st...
  • c++指针作为函数参数传递的问题的pdf版本 博客:http://blog.csdn.net/fjb2080 欢迎访问!
  • C++函数A作为参数传递给另外函数B时,实际上是把函数A作为指针传递给另外的函数B,这就涉及到了函数指针。 1.函数指针 函数指针声明如下: return_type (*p_name)(arg_list); //表示返回值为return_type,参数列表...
  • 文章目录1 C++ 值传递、指针传递、引用传递详解值传递:指针传递:引用传递:2 数组作为函数的形参2.1 一维数组传递2.2 二维数组传递总结 1 C++ 值传递、指针传递、引用传递详解 值传递: 形参是实参的拷贝,改变...
  • 当智能指针作为函数形参时,在调用此函数时,形参代表的智能指针的引用计数将+1,同时退出此函数时,该形参的引用计数将-1. 当形参不是智能指针时,调用该函数和退出该函数时,该形参的引用计数不会变化: 当...
  • 琢磨着用c++写个排序二叉树,被c++蹩脚的语法折腾得不要不要的,最要命的地方就是我将main函数里面的结构体传递给函数的时候,在函数里面做的修改不会使得main函数里的实参也变化,见鬼了,讲道理不是指针传递会修改...
  • C#调用C++DLL,C++DLL中的函数参数包含指针。 绝对可用。
  • C++之数组作为函数参数

    千次阅读 2021-01-14 21:50:44
    好消息,好消息,数组也可当参数啦!!! 长这样, void arr(int a[]) ...void arr(int a[])//数组名作为函数参数,传递的是一个地址(或常量指针) { int i; for(i=0;i<5;i++) { printf("%d\
  • Qt C++ 函数指针作为函数参数

    千次阅读 2019-03-07 10:42:23
    1:普通函数作为函数的参数 void ppp(int a,int b) { qDebug()&lt;&lt;a&lt;&lt;b; } void cmp(int a,int b,void(*hh)(int,int)) { hh(a,b); } void MainWindow4::on_pushButton_2_clicked() ...
  • C++函数指针、指针函数、返回值为函数指针的函数浅谈 引言 函数指针、指针函数是C中重要而容易混淆的概念,博主将通过两个实例来说明这两个截然不同的概念。 而返回值为函数指针的指针函数就更难理解了,放在文章的...
  • c++ 对象作为参数,指针作为参数,引用作为参数

    千次阅读 多人点赞 2018-10-14 22:53:44
    c++ 对象作为参数,指针作为参数,引用作为参数
  • C++函数参数类型为指针指针

    万次阅读 2018-08-08 08:48:02
    1 参数类型是非指针情况 例如,有如下函数 void func(char a) { a = 'a'; return; } 使用如下方式调用func()函数 char b = 'b'; func(b); 此时,变量a是func()函数的形参,变量b是func()函数的实参...
  • C++中一个函数作为作为另一个函数的参数:  把函数名作为参数就是函数的地址了. 要将函数名作为参数,需要使用函数指针。 函数指针的定义格式为 ret_type (*var_name)(arg_list); 表示返回值为ret_type...
  • 方法:需要将指向该指针指针作为参数传递给函数,再在函数中修改(即指针指针作为参数传递给函数) //函数定义 void user(void ** ppanonymity){ MyClass* target=new MyClass(); *ppanonymity=target; } ...
  • 二级指针作为函数参数

    千次阅读 2018-12-05 09:24:46
    1.用一级指针实现strlen int my_strlen1(char *str) { int count = 0; int i = 0; if (NULL == str) { return -1; } while (*str != '\0') { str++; count++; }...
  • ``` 函数实现 void swap(int &a, int &b) { int tmp = a; a = b; b = tmp; ...函数使用: ...如上所示,swap函数传递进来的是两个整形变量的地址,有两个问题 ...初学c++,还望大家多多提点指教,先谢谢各位了
  • 一、使用指针函数返回值:   1、当使用指针做为函数的返回值时,主函数处的char *p;将获得调用函数char *pf;的值,即一个地址值,如oxAE72。此时需要我们注意的是该地址值所指向的空间是否存在(即已向操作...
  • C++ 指针的引用做函数参数

    千次阅读 2018-08-19 11:13:35
    #include&lt;iostream&gt; using namespace std;...//二级指针函数参数 //在被调用函数,获取资源 int getTea(Teacher **p) { Teacher* tmp = NULL; if (p == NULL) { return -1;...
  • 本文内容出自《高质量C、C++编程指南》。阅读之后理解,然后通过自己的话和例子讲清楚,...1、数组作为函数参数进行传递时,该数组自动退化为同类型的指针。 2、指针参数是如何传递内存的 3、使用指针参数传递内存
  • 指针和引用 作为函数参数

    千次阅读 2018-11-05 18:23:11
    * 有两个作用,一个是作为标识符来表示这是一个指针(声明变量时的等号左边),也就是说存放的是地址,另外一个是作为运算符来取值(赋值等号左边)。 int *p=NULL; int a = 1; p = &amp;amp;a; cout&amp;lt;&...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 527,227
精华内容 210,890
关键字:

c++指针作为函数参数

c++ 订阅