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";
test(arr);
MessageBox(arr); //弹出1
}void CDlgTestDlg::test(TCHAR* pChar)
{
pChar="2"; //这里修改了值
MessageBox(pChar); //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢?
}
这样定义的字符串指针是const的
{
char arr[10]="1";
test(arr);
MessageBox(arr); //弹出1
} void CDlgTestDlg::test(char* pChar)
{
pChar="2"; //这里修改了值
MessageBox(pChar); //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢?
}结果还是一样...请高手指点
这样定义的话,你在这个函数中,如果修改pChar指向的地址的内容,那么在外部函数中也会有效;如果是修改pChar本身的地址,那么对外部来说是没有意义的。因为就这个指针的地址来说,相当于是值传递。如果希望改这个指针的地址,请用TCHAR** pChar
pChar[0]='2'; //这里修改了值 你还没有理解传值的含义啊
cannot convert from 'char [2]' to 'char'
还是cannot convert from 'char [2]' to 'char'
我是修改它的值,并没有修改地址:
void CDlgTestDlg::test(char* pChar)
{
pChar="2"; //这里修改了值
MessageBox(pChar); //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢?
}
同样,如果你想改变一个int*类型的实参,就需要传递指向int*类型的指针来达到目的,即二级指针。
================这是修改了地址,不是修改了值。指向存有值为2的一个空间地址。你可以调试一下,看看pChar的地址是否改变了。
现在改成这样
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如何是好?
这样行不
谢谢各位,还是不行哦#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;不知道怎么转换才好
这样行不?
{
*pChar='2';
AfxMessageBox(pChar);
}void CTttttttttDlg::OnCancel()
{
// TODO: Add extra cleanup here
char arr[10]="1";
test(arr);
AfxMessageBox(arr); //弹出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()
{
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这个变更中的地址(指针);
应该好好看看关于指针方面的内容哦。呵呵。
郁闷啊,
现在改成这样
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);
}
参数TCHAR* pChar只是个临时变量而已。
把参数修改成
void CDlgTestDlg::test(TCHAR* &pChar) 就不一样了。
void CtestmfcDlg::test(TCHAR* pChar)
{
_tcscpy(pChar,_T("2"));
AfxMessageBox(pChar);
}void CtestmfcDlg::OnBnClickedButton2()
{
TCHAR arr[]=_T("1");
test(arr);
AfxMessageBox(arr);
}
vs8测试通过,都是2。
兄弟们,已经加分了我还有些地方不太明白
我试了一下
#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的地址不同,同样也可以达到外部修改的目的??
#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 *& '
void CDlgTestDlg::test(TCHAR* &pChar)
{
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 程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以
为两者是等价的。
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着
(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改
变。
指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来
操作动态内存。
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的地址应该是相同的
我这里运行结果是这样的,地址不一样:0012FF24:linux
0012FF74:linux
Press any key to continue
0012FF74:linux //这里0012FF74是arr变量本身存储的地址,你看看0012FF74地址里的值,应该是相同的
把&去掉,那如何输出地址呢?
说了他们是不同的变量,本身的地址肯定不同,这里我们关心的是他们里面存储的值,这个值才是我们要修改的"windows"的地址请反复体会上面这句话
我试了一下 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根本就是同一个东西的。呵呵。
从你所问的来看,你对于形参和实参的概念又没有搞清楚 哦。呵呵
回复46楼:
过奖了。
偶是GG,不是MM。
方法一:实质是通过指针,逐个修改数组中的内容(记住是修改数组中的内容,而指向常量的指针的内容是不可以更改的)
#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;
}
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类型的数组,当然就会出错了。
就下面取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按位与。
void test ( int &m )
{
m = 100 ;
}
编译后相当于
void test ( int *m )
{
*m = 100 ;
}
http://blog.csdn.net/sxbluebird
这个只是把pChar重定向到一段 大小为2,内容为 '2','\0' 的临时内存正确应该是strcpy(pChar,"2");
在这里要说明的是pString 是一个指针,arr是一个地址,
&pString 是该指针变量的地址,而&arr则是数组首字节的地址
所以&pString 和&arr 肯定是不同的
如果不用& 那么输出时 cout 会将两个都当成字符串输出,那怎么输出地址那?正确应该是
cout << (LPARAM)pString
cout << (LPARAM)&arr希望楼主能明白 指针是一个变量, 大小是4 Byte(32 位寻址),内容是另外一种数据的地址
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了?
}
{
}像这种函数,只能修改指针指向地址中的内容,并不能修改指针指向的地址。当然你用奇技淫巧除外。
{
TCHAR* arr="1";
test(arr);
MessageBox(arr); //弹出1
} void CDlgTestDlg::test(TCHAR* pChar)
{
sprintf(pChar,"2"); //只修改值,不改地址
MessageBox(pChar); //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢?
}
可以作一个这样的实验
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),所以指向的内容相同
这样是错的,TCHAR* arr="1";,arr这个指针是指向常量存储区的,其中内容是不能修改的,sprintf(pChar,"2");这句会报出xxx内存不能为write的错误
函数的参数是传递一个指针值,函数里面修改pChar的值(指针),都只是对形参的修改,函数返回后形参就自动释放了,不会影响到调用者。如果是修改指针指向的数据,才会影响到调用者。另外如果把函数定义修改一下,改为:
void CDlgTestDlg::test(TCHAR*& pChar)
这时函数的参数是引用传递,函数中对pChar的修改就会带回给调用者了。
方案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);
}
{
pChar= "2"; //这里修改了值
MessageBox( pChar ); //弹出2,已经修改了值,它传递的是地址啊,为什么上面还是弹出1呢?
}
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楼写错了,对不起!
很多人都认为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"
楼上的说法不够准确,一个常量指针是不能赋给变量指针。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";
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字节,因为数组传递给函数时造成弱化了。
}
(1)提供数组的首地址与尾地址:
void getArray(int* pBeg,int* pEnd);
这时候,把一个数组传递给函数时,要给出数组第一个元素地址与数组最后一个元素后面的字节地址。
C++预定义类型经常采用这种形式
(2)提供数组的未尾标识符
void getArray(char* szMess);
这时候,函数提取数组成员时,一遇到终结符就是结束循环。
这种函数常用于字符串
(3)提供数组首地址与尺寸
void getArray(LPCTSTR szMess,int size);
因为数组一旦传给函数就弱化也指针,也不分彼此了,所以设计函数时,有必要将数组的成员给出来。
WinAPI常采用这种方式设计函数。
{
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呢?
}