c语言中指针作为实参使用SWAP函数的问题。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言中指针作为实参使用SWAP函数的问题。相关的知识,希望对你有一定的参考价值。

#include<stdio.h>

void swap(int*a,int*b)

int*t;
t=a;a=b;b=t;

main()

int i=3,j=5,*p=&i,*q=&j;
swap(p,q);
printf("%d %d\n",*p,*q);

输出结果为什么是3 5,而不是交换后的5 3?
在swap函数中指针a、b的地址发生了互换,即指针p、q的地址也发生了互换,最后输出*p和*q应该分别是j和i(5 3)才对啊…

c语言中形参与实参的关系是:形参是实参的值副本。无论参数的类型是什么,传递到子函数中的形参只是实参的值。所以,在改变形参变量自身的值时,是与实参无关的。换句话说,形参的改变不会影响到实参。

但,如果参数类型是指针类型,则可以通过对指针变量所指向的地址中的数据进行修改,达到改变实参地址中的数据目的。

因此,使用SWAP函数进行数据交换时,必须保证两点:

    参数必须是指针类型,指向待交换的数据

    交换时,必须交换地址中的数据,而不是交换地址本身。

参考代码:

//错误的交换代码1
void swap1( int a, int b ) //参数不是待交换数据的指针

    int t=a;
    a=b;
    b=t;

//错误的交换代码2
void swap2( int *a, int *b ) 

    int *t=a;//交换形参变量本身
    a=b;
    b=t;

//正确的交换代码
void swap( int *a, int *b ) 

    int t=*a;//交换形参变量地址中的数据,指针变量不变
    *a=*b;
    *b=t;

参考技术A void swap(int*a,int*b)

int*t;
t=a;a=b;b=t; //这里交换的是指针a,b的副本,不影响指针指向的值

改为

void swap(int*a,int*b)

int t;
t=*a;*a=*b;*b=t; //这里交换的是值
参考技术B 你还没了解值传递和地址传递的本质啊。
首先 p ---> i q ----> j (p和q分别存放i和j的地址)你调用swap函数。
就会把实参的值复制一份给形参。也就是说a ----> i b ---->j。现在你在swap里面使用t指针交换了
a和b,也就是a ---> j b---->i,也就是说你交换的是指针的值!但是你想想主函数main当中p和q交换了吗??你只是复制了一份值给形参,自己本身没改变。你可以这样实验一下:
在swap函数中输出看一下:printf("a:%d\tb:%d\n",*a,*b); //你可以看一下结果是交换了的。不过随着swap函数的结束而释放了a,b的空间,然后回到main函数p和q的值还是原来的。追问

你的意思是swap的形参a、b不能影响实参p、q的意思吗?

追答

你要抓住形参的值只是实参的一个副本,你改变其本身是不能实现交换的!

如果你是这样int t; t = *a; *a = *b; *b = t;你交换的就是地址所对应的值也就是i和j的值。
此时指针a和p指向的还是i的地址,只不过i地址里面存放的是j的值了。j同理!

本回答被提问者和网友采纳
参考技术C 你的这个swap中指针参数 *a,*b 已经退化成普通的局部参数了,也就是说a和b同样也只是形参而已,只不过披了个指针的外衣,在函数体内交换的只是这两个指针本身的拷贝,而不是它们指向的内容,因此需要用解除指针的方式来交换它们指向的内容。其实这里提供指针做参数,只是为了让你有办法去访问它们的实际指向内容(实参),指针本身(形参)的交换没有任何意义。有两种改法:
1.
void swap(int *a, int *b)

int t = *a;
*a = *b;
*b = t;

2.
void swap(int &a,int &b)

int t = a;
a = b;
b = t;

swap(i,j);

c拾遗-二级指针数组内函数

1、c语言中二级指针

用途1:一般被用在多维数组的环境中,一个二级指针可以指向一个二维数组;
用途2:二级指针作为函数参数使用时,可以通过函数修改实参指针值的目的。

对于第二点用途的理解:
c语言的函数调用中存在值传递和址传递,一般使用指针达到地址传递的目的。
但实际上指针变量本身也是存在实参和形参之分,只不过由于实参指针和形参指针指向了同一区域,
所以可以达到地址传递的目的,即通过修改形参指针所指向内存空间的内容,进而达到修改实参指针指向的区域。

一旦当我们需要在函数调用中修改指针变量本身时,就需要使用二级指针了:
比方说实参指针是一个空指针,而通过形参来分配内存空间,并将该空间返回给实参;

void GetMemory(char **p,int num)

  *p=(char*)malloc(sizeof(char)*num);     //此时*p就变成了是形参本身的地址

void main()

  char *str=NULL;
  GetMemory(&str,100);                    //&str是实参的地址,所以实参和形参之间就可以直接调用
  strcpy(str,"hello");
  free(str);


上述代码的易错写法是什么样呢:

void GetMemory(char *p,int num)

      p=(char*)malloc(sizeof(char)*num);       //p是形参指向的地址

void main()

      char *str=NULL;
      GetMemory(str,100);                      //str是实参指向的地址,不能通过调用函数来申请内存
      strcpy(str,"hello");

对于上面的例子,如果GetMemory函数使用返回值的方式返回指针,则就不需要二级指针,普通指针就可以实现了。


结论:
指向指针的指针的作用: 当要修改实参指针的指向的时候,形参必须使用指向指针的指针。
当修改的是实参指针指向的内容时,则形参只需是指针即可


关于值传递:
指针传递参数本质上是值传递的方式,它所传递的是一个地址值。
值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,
即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。
值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。


2、数组内函数不参与连接
今天碰到一个很奇怪的问题,搞了半天,只把最后的发现记录一下。

struct TEST_TYPE stTest[] =

    "first", first_func,
    "seconde", second_func

在该结构体数组中,引用了两个函数first_func和second_func
如果这个数组stTest没有被使用,那么这两个函数即便没有定义,但只要声明了函数原型,编译器也是不会报错的,
换句话说,数组内的两个函数只参与编译阶段,而不参与链接,所以只要有函数声明即可。

虽然在数组中引用了这两个函数,但是这个数组并没有被使用,所以出现了上面的现象,一旦这个数组被使用,那么在链接阶段就需要函数定义。

以上是关于c语言中指针作为实参使用SWAP函数的问题。的主要内容,如果未能解决你的问题,请参考以下文章

C语言形参与实参的概念及swap函数

求教C语言指针作为实参取不到值的问题

c语言 指针传参

C语言中的函数心形参和实参分别可以为哪几种类型?函数实参可以使任意类型。。。。错在哪?

c语言swap指针

C语言中的值传参和引用传参是指啥?