指针

指针的基础:

<1>定义

ContractedBlock.gif ExpandedBlockStart.gif Code
    int a = 1;  
    
int *pa = &a;//初始化
/*
--------------------------------------------*/
    
int *pa;//(养成习惯,'*'号紧跟变量名)
    pa = &a;//(注意与上边的初始化其实是一样的,初学的话很容易被忽悠的)

 

      以上pa是一个指针,cout<<pa;输出的是它的地址

      而*pa是一个int值,cout<<*pa输出的是1;

<2>指针与其指向对象关联性

   由以上:

    假如我在上面分隔线上的代码中继续添加以下代码:

       *pa = 2;或 a = 2; 

        cout<<(*pa == a)<<endl;//输出1(true),证明是同时更新的;

<3> const与指针的使用(这个东西很阴的)

ContractedBlock.gif ExpandedBlockStart.gif Code
     const char *pa;//重点在于const是修饰int的,所以是指针指向的字符串为常量。
      char const *pa;//同上,记住,是修饰int的,“const”了“*pa”因为*pa是字符串,即其值不可改
      char * const pa; //很明显地,这个const是修饰pa的,即指针pa不能被改变(即地址不能变))
     const char * const pal;//这个简单,都不能变,指向常量字符串的常指针

<4> 指向指针的指针

ContractedBlock.gif ExpandedBlockStart.gif Code
      int *pa;//普通指针
      int **ppa;//指向指针的指针,*ppa的值是一个int*指针。
      ppa = &pa;//指向指针的指针的f赋值

<5>内存分配(堆中)

ContractedBlock.gif ExpandedBlockStart.gif Code
     char *pa;
     pa 
= new char[10];//new带构造函数!
     delete []pa;
     pa 
= (char*)malloc(100);//malloc不带构造函数 
     free(pa);
     pa 
= NULL;
     
//此处还有一个比较重要的:当使用strcpy给pa赋值时需要有足够的空间,要不会内存泄露。

 关于指针的一些问题:

<1>指向常量的指针与分配了内存的指针

ContractedBlock.gif ExpandedBlockStart.gif Code
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = “abc”;
char *str8 = “abc”;
cout 
<< boolalpha << ( str1==str2 ) << endl; // 输出什么?
cout << boolalpha << ( str3==str4 ) << endl; // 输出什么?
cout << boolalpha << ( str5==str6 ) << endl; // 输出什么?
cout 
<< boolalpha << ( str7==str8 ) << endl; // 输出什么?

答:false,false,true,true

因为str1,str2,str3,str4都是字符串数组,都有分配自己的存储空间,他们的值都是指向各自的首地址,所以不等。而str5,str6不是字符数组而是常量指针,而“abc”是以常量的形式存储与静态数据区,因为相同的常量在数据区只会分配一块空间,因此str5,str6都是指向此静态区域的头地址,str7和str8同理。

<2>关于sizeof

 

ContractedBlock.gif ExpandedBlockStart.gif Code
int getLen(char str[])//函数
{return (int)(sizeof(str)-1);}

char str[]="hello world";//从这里开始为main函数
cout<<getLen(str)<<endl;
cout
<<sizeof(str)-1<<endl;//假如是int型则需要sizeof(str)/sizeof(int)-1,其他同理

 

求输出:

:3(反白可以看见)

   11

使用数组作函数形参时数组指针自动退化为指针,因此在函数体内的sizeof只能求出指针的长度4;而在外的sizeof则能求出数值的整体长度,函数内的求长使用strlen,此函数所求长度不包括‘\0’,等于sizeof()-1;

改进方法是:

ContractedBlock.gif ExpandedBlockStart.gif Code
int getLen(char (&str)[10])
  {return sizeof(str);}
//此时只要传递一个char str[10]就可以求出其长度,不过其长度是定死的。

<3>字符串数组与指针

ContractedBlock.gif ExpandedBlockStart.gif Code
char a[] = "abcdefg";//只能是字符类型才行
  char b[] = {'a','b','c','d','e','f','\0'};//此处‘\0’不能少,少了将会输出乱码
char *pc = "abcdefg";//c指向的是一个字符串常量,因此不能对c[n]赋值,紧记与a的区别
char *pa1 = a+1;//其实a+1也是一个数组的头指针,所以pa1也是数组头指针
char *pb1 = b+2;//同上
char *pb2 = (char*)(&b+1);//这里重点,&b取的是整个数组的地址,+1的话移动的是一个数组的距离
                             
//这时pb2指向的是数组的后一个指针位置,将其类型转换为char*,则指向
                             
//的是数组最后一个元素‘\0’的后一个指针的位置
cout<<pa1<<endl;//pa1是一个数组指针
cout<<pb1<<endl;//pb1也是一个数组指针
cout<<*(pb2-2);//pb2指向b数组的最后一个数后一位后向前跳两个位置,跳到了f处

求输出:

(1)bcdefg(反白可以看见)

  (2)cdef

  (3)f

<4>关于函数中的参数指针及函数中分配内存

先说明一下;

使用new或malloc来申请空间需要改变pstr,这是重点,指针作参数是否正确使用可以说就是指针的地址值(不是其指向的类型)有没有被改变的问题,将指针看作一个数据类型,那么理解会比较容易。

看以下例子:

ContractedBlock.gif ExpandedBlockStart.gif Code
void function(char *str)            
{   
   str 
= new char[12];//这种情况是错误的,因为str只是实参的一个拷贝,为其分内存不与实参有关系
    strcpy(str,"Hello world");
}
//当函数调用完毕时str这个指针拷贝将被销毁

 

 第一种方法(外部申请内存)(严格来说这种与上面讨论的无关,但是也记录下来吧):

ContractedBlock.gif ExpandedBlockStart.gif Code
void function(char *str)            
{   
    str 
= new char[12];//这种情况是错误的,因为str只是实参的一个拷贝,为其分内存不与实参有关系
    strcpy(str,"Hello world");
}
//当函数调用完毕时str这个指针拷贝将被销毁

 然后在main函数中这样使用

ContractedBlock.gif ExpandedBlockStart.gif Code
char *str = new char[12];//这里一定要分配足够的内存
str = getMemory(str);//使用返回值可行,因为在函数销毁前返回了str自身拷贝的指针str,这样可行。
delete[] str;//不过这种方法有点奇怪ORZ

第二种方法(使用双重指针):

ContractedBlock.gif ExpandedBlockStart.gif Code
void getMemory(char **ppstr)//使用指向指针的指针
ExpandedBlockStart.gif
{
     
*ppstr = new char[12];//可以修改ppstr所指向的指针
     strcpy(*ppstr,"hello world");//同上
}

在main函数中这样使用:
char *pstr;
getMemory(
&pstr);//将指针地址赋给指针的指针
cout<<pstr<<endl;
delete[] pstr;
pstr 
= NULL;

第三种方法(使用指针的引用)

ContractedBlock.gif ExpandedBlockStart.gif Code
void getMemory(char *&pstr)//引用形参不是实参的拷贝,而是传递进函数中的任意指针的别名,但是
{                            //它与指向int型对象的指针相关联,因此可以修改其值
    pstr = new char[12];
    strcpy(
*ppstr,"hello world");
}

main函数中
char *pstr;
getMemory(pstr);
cout
<<pstr;
delete[] pstr;
pstr 
= NULL;

<5>strlen的使用;

求字符串长度

ContractedBlock.gif ExpandedBlockStart.gif Code
int getLen(const char *str)//一个不适用中间变量的求字符串长度函数
{return (*str)?getLen(str+1)+1:0;}//可以说strlen就是通过字符串最后的'\0'来判断长度的

所以有如下:

ContractedBlock.gif ExpandedBlockStart.gif Code
char str[12];//不赋初值
cout<<strlen(str)<<endl;//因为没有'\0'作结束判断,所以会输出奇异的结果,记得赋初值

<6>指向数组的指针和指针数组

以下有什么不同?

ContractedBlock.gif ExpandedBlockStart.gif Code
char (*str)[20];    //str是一个数组指针,即指向数组的指针.
char *str[20];   //str是一个指针数组,其元素为指针型数据.

<7>指向类中成员的指针

ContractedBlock.gif ExpandedBlockStart.gif Code
ExpandedBlockStart.gifContractedBlock.gifclass Sample{
public:
    
int num;
ExpandedSubBlockStart.gif    
int function(){cout<<"I am Sample's function"<<endl;return 1;}
}
;

int main()
ExpandedBlockStart.gifContractedBlock.gif
{    
    
int Sample::*pnum = &Sample::num;//将*punm初始化为类Sample中num成员的地址
    Sample sam1;
    sam1.
*pnum = 2;//可以可以对所指向的内存进行复制
    cout<<sam1.num<<endl;//这时对象里的num成员被改变了
    int (Sample::*fun)() = &Sample::function;//给指向成员函数的指针赋予其成员函数的地址
    Sample sam2;//声明一个Sample类
    (sam2.*fun)();//调用指向成员函数的指针
    return 0;
}

以上是使用指向类成员函数以及成员数据的方法,其实和普通的指向函数的指针和指向数据类型的指针原理是一样的,

不同的是需要在*号的前面加上类作用域。

 

以后找到一个关于指针的细节就补上一个,请各位也看过的也帮忙提些意见吧,让我好完善一下!谢谢。

转载于:https://www.cnblogs.com/biozls/archive/2009/04/02/1428274.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值