void CDlgTestDlg::OnButton1() 
{
TCHAR* arr="1";
test(arr);
MessageBox(arr);   //弹出1
}void CDlgTestDlg::test(TCHAR* pChar)
{
pChar="2";    //这里修改了值
MessageBox(pChar);   //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢?
}

解决方案 »

  1.   

    TCHAR* arr="1"; 
    这样定义的字符串指针是const的
      

  2.   

    那这样总不可能是常量了吧void CDlgTestDlg::OnButton1() 

    char arr[10]="1"; 
    test(arr); 
    MessageBox(arr);  //弹出1 
    } void CDlgTestDlg::test(char* pChar) 

    pChar="2";    //这里修改了值 
    MessageBox(pChar);  //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢? 
    }结果还是一样...请高手指点
      

  3.   

    void CDlgTestDlg::test(TCHAR* pChar) 
    这样定义的话,你在这个函数中,如果修改pChar指向的地址的内容,那么在外部函数中也会有效;如果是修改pChar本身的地址,那么对外部来说是没有意义的。因为就这个指针的地址来说,相当于是值传递。如果希望改这个指针的地址,请用TCHAR** pChar
      

  4.   

    改成这样试试
    pChar[0]='2';    //这里修改了值 你还没有理解传值的含义啊
      

  5.   


    cannot convert from 'char [2]' to 'char'
      

  6.   


    还是cannot convert from 'char [2]' to 'char'
      

  7.   


    我是修改它的值,并没有修改地址:
    void CDlgTestDlg::test(char* pChar) 

    pChar="2";    //这里修改了值 
    MessageBox(pChar);  //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢? 

      

  8.   

    举个例子来说,如果你要改变一个int型的实参,可以通过传递指向int的指针来达到目的;
    同样,如果你想改变一个int*类型的实参,就需要传递指向int*类型的指针来达到目的,即二级指针。
      

  9.   

    pChar="2";    //这里修改了值 
    ================这是修改了地址,不是修改了值。指向存有值为2的一个空间地址。你可以调试一下,看看pChar的地址是否改变了。
      

  10.   

    郁闷啊,
    现在改成这样
    void CDlgTestDlg::OnButton1() 

    char arr[10]="1"; 
    test(&arr); 
    MessageBox(arr);  //弹出1 
    } void CDlgTestDlg::test(TCHAR** pChar) 

    *pChar="2"; 
    MessageBox(*pChar); 
    }爆出这样的错误,
    cannot convert parameter 1 from 'char (*)[10]' to 'char ** '
            Types pointed to are unrelated如何是好?
      

  11.   

    void CDlgTestDlg::test(TCHAR* pChar[]) 
    这样行不
      

  12.   


    谢谢各位,还是不行哦#include "iostream"
    using namespace std;void modifyChar(char* pChar[])
    {
    *pChar="2";
    }void main()
    {
    char arr[]="1";  //如果这里用指针,不知道如何释放,用delete会报错...
    modifyChar(&arr);
    cout<<arr<<endl;
    }cannot convert parameter 1 from 'char (*)[2]' to 'char *[]'
            Types pointed to are unrelated;不知道怎么转换才好
      

  13.   

    test((char**)&arr); 
    这样行不?
      

  14.   

    还不信了,这样呢void test(TCHAR* pChar)
    {
    *pChar='2';
    AfxMessageBox(pChar);
    }void CTttttttttDlg::OnCancel() 
    {
    // TODO: Add extra cleanup here

    char arr[10]="1";
    test(arr);
    AfxMessageBox(arr);  //弹出1
    }
      

  15.   

    若用:
        void CDlgTestDlg::OnButton1() 
       { 
         TCHAR* arr="1"; 
         test(arr); 
         MessageBox(arr);  //弹出1 
       }    void CDlgTestDlg::test(TCHAR* pChar) 
       { 
         pChar="2";    //这里修改了值 
          MessageBox(pChar);  //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢? 
       }
    则改成:
        void CDlgTestDlg::OnButton1() 
       { 
         TCHAR* arr="1"; 
         test(arr); 
         MessageBox(arr);  //弹出1 
       }    void CDlgTestDlg::test(TCHAR* pChar) 
       { 
         * pChar="2";    /*指针和指针所指向的对象要区分开来的*///这里修改了值 
          MessageBox(pChar);  //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢? 
       }若用:
        郁闷啊, 
         现在改成这样 
          void CDlgTestDlg::OnButton1() 
         { 
          char arr[10]="1"; 
          test(&arr); 
          MessageBox(arr);  //弹出1 
         }      void CDlgTestDlg::test(TCHAR** pChar) 
         { 
            *pChar="2"; 
             MessageBox(*pChar); 
         }      爆出这样的错误, 
          cannot convert parameter 1 from 'char (*)[10]' to 'char ** ' 
            Types pointed to are unrelated 
         如何是好?
    则改成:
         
        void CDlgTestDlg::OnButton1() 
        { 
          char arr[10]="1"; 
          test(&arr); 
          MessageBox(arr);  //弹出1 
        }     void CDlgTestDlg::test(TCHAR* pChar) //这里没有必要用指针的指针的
        { 
          *pChar="2"; 
          MessageBox(*pChar); 
        } 说明: 
        在定义时,char* cp; //中的*是表示定义一个指针;
        在使用时, *cp="abc"; //中的*是表示cp所指向的对象;
                   cp=&cp;//此时的cp才表示cp这个变更中的地址(指针);
      应该好好看看关于指针方面的内容哦。呵呵。
      

  16.   

    不小心,没有看仔细,这里还得再改一下:若用: 
        郁闷啊, 
        现在改成这样 
          void CDlgTestDlg::OnButton1() 
        { 
          char arr[10]="1"; 
          test(&arr); 
          MessageBox(arr);  //弹出1 
        }     void CDlgTestDlg::test(TCHAR** pChar) 
        { 
            *pChar="2"; 
            MessageBox(*pChar); 
        }     爆出这样的错误, 
          cannot convert parameter 1 from 'char (*)[10]' to 'char ** ' 
            Types pointed to are unrelated 
        如何是好? 则改成: 
        
        void CDlgTestDlg::OnButton1() 
        { 
          char arr[10]="1"; 
          test(arr); //arr本身就已经代表了一个地址了,所以这里没有必要再作引用了
          MessageBox(arr);  //弹出1 
        }     void CDlgTestDlg::test(TCHAR* pChar) //这里没有必要用指针的指针的 
        { 
          *pChar="2"; 
          MessageBox(*pChar); 
        } 
      

  17.   

    楼上test里面的*pChar="2"; 应该用单引号
      

  18.   

    “pChar="2";    //这里修改了值 ”这里不是修改了值,而是修改了pChar指向的地址。这样修改不会对OnButton1() 有任何影响。
    参数TCHAR* pChar只是个临时变量而已。
    把参数修改成
    void CDlgTestDlg::test(TCHAR* &pChar) 就不一样了。
      

  19.   

    楼主好象地址区赋值pChar="2"; 并没给指针指向内容区赋值,应*pChar="2"; 
      

  20.   


    void CtestmfcDlg::test(TCHAR* pChar)

    _tcscpy(pChar,_T("2"));
    AfxMessageBox(pChar);
    }void CtestmfcDlg::OnBnClickedButton2()
    {
    TCHAR arr[]=_T("1");
    test(arr); 
    AfxMessageBox(arr);
    }
    vs8测试通过,都是2。
      

  21.   


    兄弟们,已经加分了我还有些地方不太明白
    我试了一下
    #include "iostream"
    using namespace std;void modifyString(char* pString)
    {
    strcpy(pString,"linux");
    cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
    char arr[10]="windows";
    modifyString(arr);
    cout<<&arr<<":"<<arr<<endl;
    }此方案的确可行,可是为什么pString,arr的地址不同,同样也可以达到外部修改的目的??
      

  22.   


    #include "iostream"
    using namespace std;void modifyString(char*& pString)
    {
    //strcpy(pString,"linux");
    pString="linux";
    cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
    char* pChar="windows";
    modifyString(pChar);
    cout<<&pChar<<":"<<pChar<<endl;
    }此方法也是可以的,但如何把pChar改成数组呢?
    #include "iostream"
    using namespace std;void modifyString(char*& pString)
    {
    //strcpy(pString,"linux");
    pString="linux";
    cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
    char pChar[10]="windows";
    modifyString(pChar);
    cout<<&pChar<<":"<<pChar<<endl;
    }
    这样就不行了,
    cannot convert parameter 1 from 'char [10]' to 'char *& '
      

  23.   

    最简单的
    void CDlgTestDlg::test(TCHAR* &pChar) 
      

  24.   

    void CDlgTestDlg::OnButton1() 

    TCHAR* arr="1"; 
    test(arr); 
    MessageBox(arr);  //弹出1 
    } void CDlgTestDlg::test(TCHAR* pChar) 

    pChar="2";    //这里修改了值 
    MessageBox(pChar);  //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢? 
    }TCHAR* arr="1";
    指针arr指向常量字符串"1",常量字符的内容是不能改变的,此时相当于定义了一个const TCHAR *arr = "1";
    如要改变其值,arr[0]="2",此时编译不会报错,但程序运行时会警告Written某块内存区域失败。
    指向常量的指针,我们不能改变其内容,却可以让它指向另外的内存空间,如:
    TCHAR *arr1="1";
    TCHAR *arr2="2";
    arr2 = arr1;
    此时arr2与arr1指向了同一块内存空间,这块内存空间的内容是"2",楼主用形参的形式改变输入值,此时就要用到指针或者引用才能改变,原来的值本身就是一个指针,此时就需要用到指向指针的指针了。
    另外要注意数组与指针的区别:
    C++/C 程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以
    为两者是等价的。
    数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着
    (而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改
    变。
    指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来
    操作动态内存。
      

  25.   

    #include "iostream"
    using namespace std;void modifyString(char* pString)
    {
        strcpy(pString,"linux");//这里pString的值就是arr的值,也就是"windows"的开始地址
        cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
        char arr[10]="windows";
        modifyString(arr);//这里传递的arr是个地址,也就是“windows”的开始地址
        cout<<&arr<<":"<<arr<<endl;
    }"此方案的确可行,可是为什么pString,arr的地址不同,同样也可以达到外部修改的目的??"调试看看,pString,arr的地址应该是相同的
      

  26.   


    我这里运行结果是这样的,地址不一样:0012FF24:linux
    0012FF74:linux
    Press any key to continue
      

  27.   

    将cout输出的arr和pString前面的"&"去掉,你加了&输出的是它们本身的存储地址,而不是它们存储的值,你想想,它们本身也是变量,也是要地方来存储的,显然它们是不同的2个变量,当然存储地址不同,但是注意它们里面存储的值是相同的
      

  28.   

    如你上面所说0012FF24:linux //这里0012FF24是pString变量本身存储的地址,你看看0012FF24地址里的值,应该是相同的
    0012FF74:linux //这里0012FF74是arr变量本身存储的地址,你看看0012FF74地址里的值,应该是相同的
      

  29.   


    把&去掉,那如何输出地址呢?
      

  30.   


    说了他们是不同的变量,本身的地址肯定不同,这里我们关心的是他们里面存储的值,这个值才是我们要修改的"windows"的地址请反复体会上面这句话
      

  31.   

    我还有些地方不太明白 
    我试了一下 C/C++ code#include "iostream"
    using namespace std;void modifyString(char* pString) 
    {
        strcpy(pString,"linux");
        cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
        char arr[10]="windows";
        modifyString(arr);
        cout<<&arr<<":"<<arr<<endl;
    }此方案的确可行,可是为什么pString,arr的地址不同,同样也可以达到外部修改的目的??
    注意:也许pString,arr的地址可能有不同的,然而它们里面的内容确实是一样的,都是指向"windows"这个字符串所在内存的首地址。在C、C++中数组名(如arr)、数组第一个数的地址(如&arr[0])都是指向数组的首地址的哦。呵呵。事实上是:
    void modifyString(char* pString) //这里的pString是形参,即在这里告诉编译系统:我在调用这个函数的同时,
              //要给它一个参数,这个参数是指向一个指针(地址),这个指针所指向的数据类型是:字符或者是字符串类型
    {
        strcpy(pString,"linux");
        cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
        char arr[10]="windows";
        modifyString(arr); //在这里,我们调用了这个函数,所以我们把"windows"这个字符串的首地址作为实参
                              //传递给该函数。
        cout<<&arr<<":"<<arr<<endl;
    }所以说,在这段代码中pString,arr根本就是同一个东西的。呵呵。
    从你所问的来看,你对于形参实参的概念又没有搞清楚 哦。呵呵 
      

  32.   


    回复46楼:
       过奖了。
       偶是GG,不是MM。
      

  33.   

    实现的方法可以有多种,大致介绍一下原理,欢迎探讨:
    方法一:实质是通过指针,逐个修改数组中的内容(记住是修改数组中的内容,而指向常量的指针的内容是不可以更改的)
    #include "iostream"
    using namespace std;void modifyString(char* pString)
    {
        strcpy(pString,"linux");
        //实质是*pString = 'l'; pString++; *pString = 'i'; pString++; .......
        cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
        char arr[10]="windows";
        modifyString(arr);
        cout<<&arr<<":"<<arr<<endl;//运用结束后arr中的内容实际是"linux\0s\0\0\0",数组中的s还在,只是没有打印出来

    方法二:通过引用生成pchar的别名pString,pString更改了,pchar也就更改了
    #include "iostream"
    using namespace std;void modifyString(char*& pString)
    {
        //strcpy(pString,"linux");
        pString="linux";
        cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
        char* pChar="windows";
        modifyString(pChar);
        cout<<&pChar<<":"<<pChar<<endl;
    }
    方法三:通过指针的指针更改,pString指向pChar的地址,pString和pChar最终指向同一块内存空间
    #include "iostream"
    using namespace std;void modifyString(char **pString)
    {
        //strcpy(pString,"linux");
        *pString="linux";
        cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
        char *pChar="windows";
        modifyString(&pChar);
        cout<<&pChar<<":"<<pChar<<endl;
    }
      

  34.   

    include "iostream"
    using namespace std;
    void modifyString(char*& pString) [color=#FF0000]//此处的形参的意思是:引用一个char类型的指针。

    {
        //strcpy(pString,"linux");
        pString="linux";
        cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
        char* pChar="windows";
        modifyString(pChar);//此处给的实参类型与函数声明中的形参类型相符。
        cout<<&pChar<<":"<<pChar<<endl;
    }此方法也是可以的,但如何把pChar改成数组呢? include "iostream"
    using namespace std;void modifyString(char*& pString)//此处的形参的意思是:引用一个char类型的指针。
    {
        //strcpy(pString,"linux");
        pString="linux";
        cout<<&pString<<":"<<pString<<endl;
    }void main()
    {
        char pChar[10]="windows";
        modifyString(pChar); //此处给的实参类型与函数声明中的形参类型不符。
                                 //应该改为:modifyString((char*)pChar);以强
                                 //制将pChar所指向的地址改为char类型的指针。
        cout<<&pChar<<":"<<pChar<<endl;
    }
    这样就不行了, 
    cannot convert parameter 1 from 'char [10]' to 'char *& '[/color]这样当然不行了呀。
    在定义void modifyString(char*& pString)中,形参的意思是:引用一个char类型的指针。在第一段代码中,调用的时候,给的实参是一个char类型的指针,所以没有出错的。而在第二段代码中,在调用的时候,给的却是一个char类型的数组,当然就会出错了。 
      

  35.   


    就下面取48楼的一段代码来说明一下吧:
    方法二:通过引用生成pchar的别名pString,pString更改了,pchar也就更改了 
    #include "iostream" 
    using namespace std; void modifyString(char*& pString) 

        //strcpy(pString,"linux"); 
        pString="linux"; 
        cout < <&pString < <":" < <pString < <endl; 
    } void main() 

        char* pChar="windows"; 
        modifyString(pChar); 
        cout < <&pChar < <":" < <pChar < <endl; 

    在前面,我已经提到:就void modifyString(char*& pString)中的形参来说,是引用一个char类型的指针。
        那么,什么是“引用”呢?就“引用”来讲,有不同的含意。其中在这里的意思就是48楼所说的“别名”。这个别名只是方便你写代码,而在实际运行时,就是你所给的实参。别名只是一个名字,并不是一个变量,在实际上并不会给这个别名重新分配一个内存空间的。例如我们把main()改下:
    void main() 

        char* pChar1="windows"; 
        char* pChar2="UNIX";     
        modifyString(pChar1); 
        modifyString(pChar2);
        cout < <&pChar1 < <":" < <pChar1 < <endl; 
        cout < <&pChar2 < <":" < <pChar2 < <endl; 
    }
    那么在实际操作中:
        第一次调用modifyString()函数时,modifyString()函数中的pString将由pChar1来代替,也就是说在此时,modifyString()函数变成:

        pChar1="linux"; 
        cout < <&pChar1< <":" < <pChar1< <endl; 
    }
        第二次调用modifyString()函数时,modifyString()函数中的pString将由pChar2来代替,也就是说在此时,modifyString()函数变成:

        pChar2="linux"; 
        cout < <&pChar2< <":" < <pChar2< <endl; 
    }
    并没有重新分配一个临时变量用以存放参数,而是直接对实参进行操作。若在函数声明中,形参不是引用,而是指针的话,如:
    void modifyString(char* pString);
    则在下面的调用中:
    void main() 

        char* pChar1="windows"; 
        char* pChar2="UNIX";     
        modifyString(pChar1); 
        modifyString(pChar2);
        cout < <&pChar1 < <":" < <pChar1 < <endl; 
        cout < <&pChar2 < <":" < <pChar2 < <endl; 
    }
    会生成临时变量,用以存放实参:
    在实际操作中:
        第一次调用modifyString()函数时,modifyString()函数中的pString将申请一个临时变量,来存放实参pChar1传来的内容,也就是说在此时,modifyString()函数变成:

        pString="linux";/*pString是一个实实在在申请的临时变量,pString中存放的内容是pChar1中的内容*/
                        /*即pString=pChar1 */ 
        cout < <&pChar1< <":" < <pChar1< <endl; 
    }
        第二次调用modifyString()函数时,modifyString()函数中的pString将申请一个临时变量,来存放实参pChar2传来的内容,也就是说在此时,modifyString()函数变成:

        pString="linux"; /*pString是一个实实在在申请的临时变量,pString中存放的内容是pChar2中的内容*/
                         /*即pString=pChar2 */ 
        cout < <&pChar2< <":" < <pChar2< <endl; 
    }
    事实上在此处的引用形参是不产生占用内存空间的,而指针形参却是要申请临时内存空间的。多说一句:
        C/C++是属于强类型语言,在定义变量、参数、函数等时,都要有明确的类型。在void modifyString(char*& pString)中,char *是表示这个参数是字符型的一个指针,&pString则是表示一个引用。
        注意:在函数声明时,&pString是用来表示一个引用;而在运算时&pString则表示取pString这个变量所在的内存的地址;A&pString则表示变量A和变量pString按位与。
      

  36.   

    我想楼主是没理解指针变量存储的地址,与指针变量自身的关系.例如char *p = "windows" , 我编译一下,得到: mov dword ptr[ebp-14h],offset string "windows" (416710h)意思是把"windows"这个字符串的地址,这里即0x00416710h 放到ebp-14(例如:0X0012ff54,即p变量里面) ebp-14 是一个栈地址,即&p = ebp-14 所以p是一个栈变量,它位于从0x0012ff54 地址开始的4个字节里. 这4个字节里面存放的是0x00416710h , 而从地址0x00416710h开始的8个字节里面,放的分别是'w','i',...'s',0 等字符的ASCII码, 第8个字节存放0,表示字符串结束.     而 char p ='a' 呢?假设p 还是在0x0012ff54 这个地址,没错,这个地址存放的是a的ASCII码. char p[] = " windows" 呢? 假设p 还是在0x0012ff54 这个地址,那么从这个地址开始的8个字节存放的是"windows"的的ASCII码. 
      

  37.   

    引用的本质还是指针. 例如:
    void test ( int &m )
    {
       m = 100 ;
    }
    编译后相当于
    void test ( int *m )
    {
       *m = 100 ;
    }
      

  38.   

    我刚写了一个blog, 关于传递参数的, 大家可以参考, 讨论一下。
    http://blog.csdn.net/sxbluebird
      

  39.   

    哈哈!!以后再有人问这方面的问题,给这个URL,直接秒杀
      

  40.   

    pChar是一个局部栈变量,是一个自由指针,能随意修改其指向的内存。pChar="2";将导致这个变量指向另一个完全不同的内存。
      

  41.   

    汗毕了没见过这么修改字符串变量的
    这个只是把pChar重定向到一段 大小为2,内容为 '2','\0' 的临时内存正确应该是strcpy(pChar,"2");
      

  42.   


    在这里要说明的是pString 是一个指针,arr是一个地址,
    &pString 是该指针变量的地址,而&arr则是数组首字节的地址
    所以&pString 和&arr 肯定是不同的
    如果不用& 那么输出时 cout 会将两个都当成字符串输出,那怎么输出地址那?正确应该是
    cout << (LPARAM)pString
    cout << (LPARAM)&arr希望楼主能明白 指针是一个变量, 大小是4 Byte(32 位寻址),内容是另外一种数据的地址
      

  43.   

    很简单的一个问题,干嘛搞这么复杂。把TCHAR*看作一种类型,比如int
    void CDlgTestDlg::OnButton1() 

    int arr=1; 
    test(arr);
    CString str;
    str.Format("%d",arr); 
    MessageBox(arr);  
    } void CDlgTestDlg::test(int pChar) 

    pChar=2;    //这里修改了值
    CString str;
    str.Format("%d",pChar); 
    MessageBox(str);  //弹出2,已经修改了值,你说上面为什么弹出1?不是很明显么? 
    }
    像这样,就你想要的
    void CDlgTestDlg::OnButton1() 

    TCHAR* arr="1"; 
    test(arr); 
    MessageBox(arr);  //弹出2 
    } void CDlgTestDlg::test(TCHAR* &pChar)  //加个引用

    pChar="2";    //这里修改了值 
    MessageBox(pChar);  //弹出2,已经修改了值,上面就弹出2了? 
    }
      

  44.   

    void CDlgTestDlg::test(TCHAR* pChar) 

    }像这种函数,只能修改指针指向地址中的内容,并不能修改指针指向的地址。当然你用奇技淫巧除外。
      

  45.   

    void CDlgTestDlg::OnButton1() 

    TCHAR* arr="1"; 
    test(arr); 
    MessageBox(arr);  //弹出1 
    } void CDlgTestDlg::test(TCHAR* pChar) 

    sprintf(pChar,"2"); //只修改值,不改地址
    MessageBox(pChar);  //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢? 
    }
      

  46.   

    指针传递,也只是传递一个指针副本,实质上是重新建立了一个指针变量,只是此时,新变量指向的地址与arr指向的地方相同,所以,有&pString与&arr不同(在内存中建立的两个不同变量的地方当然是不同的),而*pString与*arr相同(即pString与arr指向的内容相同)的结果.
    可以作一个这样的实验
    main()
    {
     char aa[10]="windows";
     char aa1[10]="unix";
     long bb=reinterpret_cast<long>(aa);//bb=0x0012f6e4,aa的值是0x0012f6e4
     long cc=reinterpret_cast<long>(&aa);//cc=0x0012f6e4,内存中此处存储变量aa,值是它自己0x0012f6e4
     char *pcha=aa;            //复制指针
     long dd=reinterpret_cast<long>(pcha);//dd=0x0012f6e4
     long ee=reinterpret_cast<long>(&pcha);//ee=0x0012f6cc,内存中此处存储变量pcha,值是0x0012f6e4
    //
     pcha=aa1;                          //复制指针,其实是复制它指向的值(此值仍然是个地址)
     long ff=reinterpret_cast<long>(pcha);//ff=0x0012f6d8
     long gg=reinterpret_cast<long>(&pcha);//gg=0x0012f6cc,内存中此处存储变量pcha,值是0x0012f6d8 moChar(aa);
    }
    void moChar(char *pchar)
    {
      long hh=reinterpret_cast<long>(pchar);//hh=0x0012f6e4
      long ii=reinterpret_cast<long>(&pchar);//ii=0x0012f66c,内存中此处存储变量pchar,值是0x0012f6e4
    }
    可以看出,ee=ff,也就是说,在内存中存储变量pcha本身的地方并没有变化,变化的只是它的值(即pcha指向的内存空间)
    函数调用中,内存中存储变量pchar的地方ii=0x0012f66c,不等于存储变量aa的地方cc=0x0012f6e4,只是他们的值(他们指向的内存空间)都是hh=0x0012f6e4(bb=0x0012f6e4),所以指向的内容相同
      

  47.   


    这样是错的,TCHAR* arr="1";,arr这个指针是指向常量存储区的,其中内容是不能修改的,sprintf(pChar,"2");这句会报出xxx内存不能为write的错误
      

  48.   

    回复太多了,没看大家的回复。void CDlgTestDlg::test(TCHAR* pChar)
    函数的参数是传递一个指针值,函数里面修改pChar的值(指针),都只是对形参的修改,函数返回后形参就自动释放了,不会影响到调用者。如果是修改指针指向的数据,才会影响到调用者。另外如果把函数定义修改一下,改为:
    void CDlgTestDlg::test(TCHAR*& pChar)
    这时函数的参数是引用传递,函数中对pChar的修改就会带回给调用者了。
      

  49.   

    总结一下,回到问题开始的地方,上面最简单的两种方案,分别对应数组型和指针型的参数,不能交叉使用
    方案1:
    void CDlgTestDlg::OnButton1() 

    char arr[10]="1"; // 数组型参数
    test(arr); 
    MessageBox(arr);
    } void CDlgTestDlg::test(char* pChar) // 不能改变pChar指向的地址

    pChar[0]='2';  
    MessageBox(pChar); 
    }方案2:
    void CDlgTestDlg::OnButton1() 

    TCHAR* arr="1"; //指针型参数
    test(arr); 
    MessageBox(arr);
    } void CDlgTestDlg::test(TCHAR* &pChar) // 能改变pChar指向的地址

    pChar="2";  
    MessageBox(pChar);  
    }
      

  50.   

    改为引用void CDDDlg::test(TCHAR* &pChar) 

    pChar= "2";    //这里修改了值 
    MessageBox( pChar );  //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢? 
    }
      

  51.   

    greatws兄眼力很准,是我粗心,调试时用的代码是:
    void CDlgTestDlg::OnButton1() 

    char arr[10]="1"; 
    test(arr); 
    MessageBox(arr);  //弹出1 
    } void CDlgTestDlg::test(TCHAR* pChar) 

    sprintf(pChar,"2"); //只修改值,不改地址 
    MessageBox(pChar);  //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢? 

    在71楼写错了,对不起!
      

  52.   

     "2",这是一个地址。传递时pChar与arr值相同,都是指向"1"的地址,pChar="2",改了pChar,指向了"2",并没有改arr的内容。
      

  53.   


    很多人都认为test(TCHAR* pChar)函数中,参数是指针传递,所以传递过程中没有对实参进行复制。实际上,这里仍然传递的是实参arr的拷贝。上面的代码我写一下函数调用过程中发生的变化:const char* pTmp1 = "1";  //这里是编译器的行为,为常量字符串"1"分配空间
    TCHAR* arr = pTmp1;       
    //test(arr);
    //下面是test的执行过程
    TCHAR* pChar = arr;
    const char* pTmp2 = "2";  //同上
    pChar=pTmp2; //注意:这里是将pChar指向了另一个const char*也就是"2"所在的地址。
                   //并不是改变了arr的地址的内容。
    MessageBox(pChar);//显然这时候会弹出2,因为pChar指向"2"
    //此时test(TCHAR* pChar)函数执行完毕,没有人对arr进行修改。
    MessageBox(arr); //因为没有人对arr修改,所以这里显示"1"
      

  54.   


    楼上的说法不够准确,一个常量指针是不能赋给变量指针。OnButton1函数中的第一个行代码,只不过定义了一个TCHAR指针,然后向这个指址指向的内容以"1"来填充。编译器对代码进行了优化,把它看成是const char指针。
    因为arr并不是严格意义上的常量指针,所以可以将它传给函数test.在参数传递过程中,产生了如下代码:
    TCHAR* pChar=arr; //指针pChar是一个局部值,它不是arr的别名。
    pChar="2" //修改了pChar的地址,而函数外的arr的内容没有修改,这么一来pChar将是一个全新地址。
    MessageBox(pChar);  //这时pChar将显示出局部指针指向的内容。为了看到改变的字符串内容,函数可以这么设计:
    void test(TCHAR* pChar) 


    pChar[0]=_T('2');
            //也可以写成_tcscpy(pChar,_T("2"));
    MessageBox(NULL,pChar,NULL,MB_OK);  
    } void OnButton1() 

    TCHAR arr[10]; 
    _tcscpy(arr,_T("1"));
    test(arr); 
    MessageBox(NULL,arr,NULL,MB_OK);  

    因为语句_tcscpy(pChar,_T("2"));和pChar[0]=_T('2');
    并没有对地址进行改变,所以OnButton1中的消息框显示出2.
    这也就是为什么不能把一个字符串常量赋给一个字符串数组,因为字符串数组在它定义时地址已经确定,而且不会改变,给它赋予常理意味着要修改字符串地址。或者设计一个含二级指针的函数:
    void test(TCHAR** pChar) 


    *pChar=_T("2");
    MessageBox(NULL,*pChar,NULL,MB_OK);  
    } void OnButton1() 

    TCHAR* arr=_T("1"); 

    test(&arr); 
    MessageBox(NULL,arr,NULL,MB_OK);  
    }
    如果test函数中第一行代码修改成_tcscpy(*pChar,_T("2")),就会出错。这是因为pChar值与外部的arr相同,而arr指向的是一个常量,所以不能对pChar指向的内容操作。
    采用二级指针,在修改指针值的情况下看到修改后的内空。由于test中接受的是指针的地址,即使它赋值给局部变量,指针值修改之后,二级指针值仍然不变。当函数返回之后,arr的值被改变,不再指向常量"1",而是指向常量"2"; 
      

  55.   

    面试的时候,排错题,经常会出现这种题目,什么传递数组指针时候,为什么会报错,传递二级指针时,为什么不会错,传递字符指针,为什么会报错,花样很多呀。楼主去做一点C++面试题,保证收益很多的。
    1.TCHAR* pTmp1="1",默认情况下是const TCHAR*,这是编译器造成的2如果定义了如下两个指针
    TCHAR* pTmp1="1";
    TCHAR* pTmp2="1";
    那么编译器会把这两个字符串放在一块地址;3.C++中定义:
    #ifndef _UNICODE
    #define w_char TCHAR
    #else
    #define char TCHAR,
    那么一来
    TCHAR* sz,sz2;
    其中sz2是TCHAR类型,而sz却是TCHAR*
    造成每定义一个TCHAR指针,每个变量前要加*4.如果定义了这么一个指针:
    typedef TCHAR *PCHAR
    那么const PCHAR pstring;
    pstring是什么类型呢,许多个认为是const指针,但是它但是常指针,也就是说这个指针的地址是不变,而指针指向的内容是可以改变的。const PCHAR中的const是修饰指针,而不是修饰变量。5.如果定义了这么几行代码:
    const TCHAR* szMess=_T("12131");
    TCHAR* sz1=szMess;
    编译器就会报错,因为常量指针是不能赋给变量指针的,如果这种赋值行为是合法的,那么用户可以修改sz1所指向的内容,因此const指针szMess所指向的内容也会跟着变。之所以楼主的代码不会报错,是因为TCHAR* arr=_T("22"),原本就是变量指针,所以传给函数时没有报错。一个普通指针是可以赋给一个常量指针。6.因为存在着第5条这种限制,设计函数的参数时,可以使用const指针的情况下,尽量使用const指针,例如:
    void print(const TCHAR* szMess)
    这个函数可以接受const指针,与变量指针
    而如果有这么一个函数:
    void print(TCHAR* szMess)
    这个函数可以接受变量指针,但不能接受常量指针。7.当在设计函数时,为了调用者能够接受地址改变后的字符串,经常这么设计函数:
    void print(LPTSTR* lpstr,int size)
    第一个参数使用二级指针,使得调用者可以接受变化后的地址
    第二个参数使用整数,表示当函数要赋给字符串的内容过长时,可以重新分配一个指针给lpstr指向的内容。不至于溢出
    LPTSTR print()
    这种函数通过动态分配一个指针给调用者,但是调用者使用完这个指针后就需要删除它。8.大多数情况下,数组会转化成指针,但如下三种情况除外:
    (1)TCHAR ar[10]
    int a=sizeof(ar);
    a将得到10个TCHAR的尺寸,也就是20个(unicode环境)或10个字节(ANSI环境)
    (2)TCHAR ar[10];
    void print(TCHAR (&ref)[10])
    当ar传给函数print时,ar会转化成具有10个成员的TCHAR数组的引用。
    (3) TCHAR ar[10];
    TCHAR (*par)[10]=&ar;
    把一个数组名字取地址时,数组会转化成一个确定成员数量的数组指针。9.指针就是一个地址,无论它出现在哪里都是一个4字节的
    void *pa;
    TCHAR* pb=new TCHAR;
    TCHAR* pc=pb;
    TCHAR* pb=_T("1213");
    int* pia,a=1;
    pia=&a;
    以上所有的指针都是4字节的。
    void print(int* a)
    {
      //当数组传递本函数时,指针a就是4字节,因为数组传递给函数时造成弱化了。
    }
      

  56.   

    10.在传递数组给函数时,一般参数形式有三种:
    (1)提供数组的首地址与尾地址:
    void getArray(int* pBeg,int* pEnd);
    这时候,把一个数组传递给函数时,要给出数组第一个元素地址与数组最后一个元素后面的字节地址。
    C++预定义类型经常采用这种形式
    (2)提供数组的未尾标识符
    void getArray(char* szMess);
    这时候,函数提取数组成员时,一遇到终结符就是结束循环。
    这种函数常用于字符串
    (3)提供数组首地址与尺寸
    void getArray(LPCTSTR szMess,int size);
    因为数组一旦传给函数就弱化也指针,也不分彼此了,所以设计函数时,有必要将数组的成员给出来。
    WinAPI常采用这种方式设计函数。
      

  57.   

    通常使用 CONST 限制的变量是不能改变其值的。
      

  58.   

    void CDlgTestDlg::OnButton1() 

       TCHAR* arr="1"; 
       test(arr); 
       MessageBox(arr);  //弹出1 
    } void CDlgTestDlg::test(TCHAR* pChar) 

       pChar="2";    //这里修改了值 
       MessageBox(pChar);  //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢? 
    }"1"和"2"都是const变量,arr最初指向存放"1"的静态变量区
    在调用test后,编译器会给参数arr构造一个临时副本_arr在调用pChar="2"时,程序希望将arr指针从指向"1"变成指向"2"
    执行上面这步操作的结果是,临时副本_arr指向了"2",但是arr仍指向"1",导致了楼主所描述的结果可以将程序改成:
    void CDlgTestDlg::OnButton1() 

       TCHAR* arr="1"; 
       test(arr); 
       MessageBox(&arr);  //弹出1 
    } void CDlgTestDlg::test(TCHAR** pChar) 

       *pChar="2";    //这里修改了值 
       MessageBox(*pChar);  //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢? 
    }