user-0 提问: swap 指针问题请教

回复:
user: user-1
content: 传值调用与传址调用的区别

user: user-2
content: swap(int x,int y){     int temp;     temp=x;     x=y;     y=temp; }  swap(m, n); 只是将m, n的副本, 在此函数内部互换下。 实参m， n 并没有变化。  只能用指针， void swap(int *x,int *y)；实现。 指针值的也没有变化， 改变的是指针所指的内存的内容。。

user: user-3
content: 为什么问来问去总是这些问题。。这个网上一搜都到处都是了吧

user: user-4
content: 调用函数时，会把所有参数变量复制到函数中，不管你怎么修改函数里面的那个变量，和调用该函数时传给这个函数的变量没有关系 用指针可以修改内存，把函数外的指针复制到函数里，两个指针依然指向同一块内存，也就是同一个变量，所以修改函数里面的那个指针指向的变量，也就等于修改函数外面的那个指针指向的变量

user: user-5
content: 大部分语言都有按值传参，按引用传参的区别

user: user-6
content: 你要交换int,参数用int* 你要交换int*,参数用int** 你要交换T, 参数用T*

user: user-7
content: 此外还有：      /* * swap - swap value of @a and @b   */  #define swap(a, b) \         do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)   我觉得看明白这些就可以

user: user-7
content: http://bbs.csdn.net/topics/350206749  #include <iostream> using namespace std; /*为了便于区分讲解，函数中的临时参数标识符不用void fun1(int x,int y)代码中的x，y而用a与b替换 *另外，程序解释不用太多的语法，用通俗的话语依旧可以很有趣。“千言万语不如一个好例子”。下面 *我就遵循这个原则去解释我对问题的理解。 */  /*fun1中的参数ab是在函数fun1调用的时候才分配内存单元，也就是临时变量，在函数调用结束后 *自动销毁。当调用fun1(x,y)时，实际相当于fun1(int a=x,int b=y)或者fun1(int a=*x0,int b=*y0); *因此ab有自己的内存，通过调用ab也有了自己的值，那么在函数中无论对ab的什么操作，都只影响到ab， *而与xy无关。 *用一个比喻更好解释：假设我国要引进俄国某个机型的战斗机生产线，那么通过政府(main())批准审核投资 *这个生产线就建造成了（fun1（））;那么这个生产线与俄国内的同样的生产线之间是相互独立的 *（ab与xy的区别），唯一的联系是：通过政府(main())出钱购买他们的技术或者设配（调用，同时a=x,b=y） *经过这样之后，我们无论在这个生产线上造什么牛逼的歼十，十一。都与俄国本部的生产线无关了，他们关不 *着也问不着！ */ void fun1(int a,int b) {//这个函数交换数值是:治标不治本     int tem;     tem=a;     a=b;     b=tem;     cout<<"fun1(int a,int b):a="<<a<<",b="<<b<<endl; }  /*fun2数值的交换效果依旧是治标不治本。而且要注意它与fun3的区别，虽然它们形参格式相同 *临时开辟三个临时指针，a、b、tem。同样三者都是局部变量，与函数“老大”“同年同月同日同时生” *而且“同年同月同日同时死”（很像三国的桃园三结义，都是忠诚的卫士）。fun2中的指针ab存储的 *是x，y的地址，等价于fun2(int *a=&x,int *b=&y)或者fun2(int *a=x0,int *b=y0)；fun2中的代码 *实现的是把指针ab存的地址值交换一下，实质是交换了ab指针的指向，因此ab存储的地址中存储 *值还是没有改变。而且也不影响外界指针x0y0的指向,在fun7中会看到与不同 *可以通过fun2中注释掉的语句验证一下 */ void fun2(int *a,int *b) {     //cout<<"a存的地址值"<<a<<"\nb存的地址值"<<b<<endl;     //cout<<"a指向的值"<<*a<<"\nb指向的值"<<*b<<endl;     int *tem;     tem=a;     a=b;     b=tem;     cout<<"fun2(int *a,int *b):*a="<<*a<<",*b="<<*b<<endl;     //cout<<"a存的地址值"<<a<<"\nb存的地址值"<<b<<endl;     //cout<<"a指向的值"<<*a<<"\nb指向的值"<<*b<<endl; }    /*fun3交换数值的效果才算治本了！ *局部变量问题不再解释。通过临时指针ab中存储的地址，找到真正要交换的xy值，然后把他们交换了！ *公安局喜欢这样干活，他们总是不能直接找到犯罪主谋，但是他们会找到一些知道主谋线索的其他非主谋 *嫌疑犯，那么通过抓住他们然后用刑折磨，这要比直接找主谋要容易些，当然这样做有些曲折（绕弯）！但也很有效 *同理，假设你在家里建一个小金库（这里的xy），那么你要设置好自己的密码（xy的地址），然后死死地 *记在脑海（指针）中。每当想打开看看让自己踏实些，你就要从脑海中找到这个密码然后打开它。然而技术 *在飞跃，假设已有《盗梦空间》中的技术，我想改变你的意念（fun3）或者从梦中偷你的思想或者秘密 *接下来的情节会更精彩... */ void fun3(int *a,int *b) {     int tem;     tem=*a;     *a=*b;     *b=tem;     cout<<"fun3(int *a,int *b):*a="<<*a<<",*b="<<*b<<endl; }   /*fun4表述的是“引用” *引用的通俗解释：相当于一个人有多个名字或者外号一样。无论你叫他哪个名字，他都应。 *因此引用很像：一个变量有多个标识符（这样说稍微有些不当）。如果a是变量b的引用，那么ab是同一对象 *通过调用fun4(x,y)或者fun4(*x0,*y0).那么临时变量ab分别是xy与*x0与*y0的引用了。对ab操作就相当于在 *main中直接操作xy */ void fun4(int &a,int &b) {     int tem;     tem=a;     a=b;     b=tem;     cout<<"fun4(int &a,int &b):a="<<a<<",b="<<b<<endl; }   /*fun5参数采用指向指针的指针，这比fun2，fun3还要绕弯子，但这里依旧要注意fun5与fun7的区别 *fun5依旧治标不治本，fun6才能治本，他们实质和fun2与fun3类似，只不过比它们要多一层指针 *既然多一层指针那么在调用的时候传递的实参就必须是指针的地址，而不能是别的。等价于 *fun5(int **a=&x0,int **b=&y0) *换用上面的比喻：相当于在《盗梦空间》里进入第二层梦里偷意念了。c++里没有拓展到第三，四层梦里 *去偷东西！也就是没有***a或者*****a。因为两层处理的很好了！ */ void fun5(int **a,int **b) {     int **tem;     tem=a;     a=b;     b=tem;     cout<<"fun5(int **a,int **b):**a="<<**a<<",**b="<<**b<<endl; }   /*fun6和fun3有相同的实质，只是多一层指针 */ void fun6(int **a,int **b) {     int tem;     tem=**a;     **a=**b;     **b=tem;     cout<<"fun6(int **a,int **b):**a="<<**a<<",**b="<<**b<<endl; }  /*fun7实现与fun2不同效果，上面我已经提到了。 *fun2结果是函数内部的交换不会影响到外面指针的指向，但是这里不同了，fun7函数实现了指针x0y0 *指向的交换。但却没有影响到xy的值的交换。就因为多了一个“引用（&）”。而fun2中是开辟的临时指针变量 *明白引用就能明白这里的效果。 */ void fun7(int *&a,int *&b) {     int *tem;     tem=a;     a=b;     b=tem;     cout<<"fun7(int *&a,int *&b):*a="<<*a<<",*b="<<*b<<endl; }  /*这里达到的效果同fun3，二者一定程度上可以互相替换，只不过调用时有些区别！ */ void fun8(int *&a,int *&b) {     int tem;     tem=*a;     *a=*b;     *b=tem;     cout<<"fun8(int *&a,int *&b):*a="<<*a<<",*b="<<*b<<endl; } int main() {     int x=13,*x0=&x,&x1=x;     int y=250,*y0=&y,&y1=y;      cout<<"\n调用前main():x="<<x<<",y="<<y<<endl;     fun1(x,y);     cout<<"调用后main():x="<<x<<",y="<<y<<endl;      //fun1(&x,&y);//错误      cout<<"\n调用前main():*x0="<<*x0<<",*y0="<<*y0<<endl;     fun1(*x0,*y0);//这与上面的fun1调用没有区别     cout<<"调用后main():*x0="<<*x0<<",*y0="<<*y0<<endl;        cout<<"\n调用前main():*x0="<<*x0<<",*y0="<<*y0<<endl;     fun2(x0,y0);//把指针的地址传递过去，     cout<<"调用后main():*x0="<<*x0<<",*y0="<<*y0<<endl;      cout<<"\n调用前main():x="<<x<<",y="<<y<<endl;     fun2(&x,&y);//把指针的地址的副本传递过去（按值传递），依旧不会影响原来的指针x0y0的指向     cout<<"调用后main():x="<<x<<",y="<<y<<endl;        cout<<"\n调用前main():*x0="<<*x0<<",*y0="<<*y0<<endl;     fun3(x0,y0);     cout<<"调用后main():*x0="<<*x0<<",*y0="<<*y0<<endl;     cout<<"调用后main():x="<<x<<",y="<<y<<endl;      cout<<"\n调用前main():x="<<x<<",y="<<y<<endl;     fun3(&x,&y);     cout<<"调用后main():x="<<x<<",y="<<y<<endl;     cout<<"调用后main():*x0="<<*x0<<",*y0="<<*y0<<endl;        cout<<"\n调用前main():x="<<x<<",y="<<y<<endl;     fun4(x,y);     cout<<"调用后main():x="<<x<<",y="<<y<<endl;      cout<<"\n调用前main():*x0="<<*x0<<",*y0="<<*y0<<endl;     fun4(*x0,*y0);     cout<<"调用后main():*x0="<<*x0<<",*y0="<<*y0<<endl;       //fun5(&x,&y);//错误      cout<<"\n调用前main():x="<<x<<",y="<<y<<endl;     fun5(&x0,&y0);     cout<<"调用后main():x="<<x<<",y="<<y<<endl;     cout<<"调用后main():*x0="<<*x0<<",*y0="<<*y0<<endl;      cout<<"\n调用前main():*x0="<<*x0<<",*y0="<<*y0<<endl;     fun6(&x0,&y0);     cout<<"调用后main():*x0="<<*x0<<",*y0="<<*y0<<endl;     cout<<"调用后main():x="<<x<<",y="<<y<<endl;   //这里之所以把fun8调用放在fun7之前，是因为如果fun7在fun8前，那么fun7调用后x0指向y,y0指向x, //再调用fun8得到的结果不便于理解。     cout<<"\n调用前main():*x0="<<*x0<<",*y0="<<*y0<<endl;     fun8(x0,y0);     cout<<"调用后main():*x0="<<*x0<<",*y0="<<*y0<<endl;     cout<<"调用后main():x="<<x<<",y="<<y<<endl;        cout<<"\n调用前main():*x0="<<*x0<<",*y0="<<*y0<<endl;     fun7(x0,y0);     cout<<"调用后main():*x0="<<*x0<<",*y0="<<*y0<<endl;     cout<<"调用后main():x="<<x<<",y="<<y<<endl;      //fun7(&x,&y);//错误     system("pause");    return 0; }

user: user-8
content: #include <stdio.h> #define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0) char   *p1="1" ,*p2="2" ; char    c1=1   , c2=2   ; short   s1=1   , s2=2   ; int     i1=1   , i2=2   ; __int64 I1=1i64, I2=2i64; float   f1=1.0f, f2=2.0f; double  d1=1.0 , d2=2.0 ; void main() {     SWAP((int)p1,(int)p2);                printf("char *     %5s,   %5s\n",p1,p2);     SWAP(c1,c2);                          printf("char       %5d,   %5d\n",c1,c2);     SWAP(s1,s2);                          printf("short      %5d,   %5d\n",s1,s2);     SWAP(i1,i2);                          printf("int        %5d,   %5d\n",i1,i2);     SWAP(I1,I2);                          printf("__int64 %5I64d,%5I64d\n",I1,I2);     SWAP(*(int     *)&f1,*(int     *)&f2);printf("float      %5g,   %5g\n",f1,f2);     SWAP(*(__int64 *)&d1,*(__int64 *)&d2);printf("double    %5lg,  %5lg\n",d1,d2);      SWAP(c1,c1);     printf("%d\n",c1); } //char *         2,       1 //char           2,       1 //short          2,       1 //int            2,       1 //__int64     2,    1 //float          2,       1 //double        2,      1 //2