指针的初始化

通俗的讲,指针是一个地址,指针的初始化就是让指针指向一个确定的地址。*是指针的解引用符,意思是取指针指向的地址里的数据。

因此,int a;

int *p = &a;

// 这里是初始化,表示的是指针初始化为a的地址,实际相当于

int *p; p = &a;

*p = 10;

// 这是表示对指针解引用,想p所指向的地址写入10

从函数调用的角度来讲,一个函数在那里,并不会自己运行,只有你去调用它它才会运行。在函数调用发生时,C/C++实际做的是用实际参数代替形参。例如:

void func(int* a)

{

    (* a) = 12;

 }//这样操作有无问题?

int* p;

func(p); // 在这里(函数调用)的时候,实际相当于有如下过程:int *a; 

a =p;(实参代替形参); *a = 10; 因此,这样操作是否有问题,关键在于p(实参)本身是否有问题。如果p本身指向了一个确切的地址,则a=p也使a(形参)实际指向了一个确切的地址,如果p本身没初始化,那么a=p也使a实际指向了一个未初始化的地址。

下面是在一篇博客上讲述的对指针初始化的几种情况:


1.一般指针的初始化

int *p=1;

char *q=’a’;

都是错误的写法,一般应该是

int a[5],b;

int *p=a;

int *q=&b;

为什么呢?int *P=&a;运算顺序是int *(p=&a)而不是 int (*p)=(&a);一般的初始化指针可以通过以下的一些方法:

int *q=0;  int *p=NULL;

初始化指针变量q,有两个作用,首先会在当前系统堆栈区给q开辟一个随机地址&q,同时将*q(指针q所指向的空间的内容)的值修改为0。具有值NULL的指针不指向任何值。

int *p, a;

p=&a;

或者定义的时候就初始化,或者int *p=&a;

2.指针里存放的虽然是地址,而且地址长度是一样的,地址长度是一样的 sizeof(int *) 和 sizeof(char*)32位机器都是4个字节,但是定义不同类型的指针意义在于程序执行时需要确切地知道如何移动指针,以及如何读取指针所指单元的内容。

比如:int a[10];

int *p = a;

现在p指向数组的首地址 假设这个地址是0x00000000,那么*p = a[0]那么怎么指向a[1]呢?执行p = p+1后 *p=a[1]了请注意 p=p+1不是 0x00000000+1而是0x00000000+4(32位的机器上)为什么是加4而不是加因为int型在32位机器上是占四个字节 所以指向下一个数组元素的地址就需要把地址移动四个字节这就是指针需要类型的原因。

int a; 

char *p; 

a=4;/*输出的值是否相等取决于此处的赋值范围*/ 

p=&a; 

printf("%d\n",a); 

printf("%d\n",*p); 

如果a-128~128间输出都是相等的超出范围后就不一样了。 这个就像我上面说的 如果是char型 那么printf函数从指针开始读取1个字节输出,如果是int型 那么printf函数从指针开始读取四个字节 a = 4 在内存中存储的为 0x04 0x00 0x00 0x00intelCPU应该是这样存储的 不同的cpu是不一样的好像 地址依次增加)所以当当a-128~128时 printf("%d\n",a); printf("%d\n",*p); 都输出0x04 (从指针开始读取一个字节和4个字节是一样的)如果a大于128  比如在内存中存储的为 0x04 0xFF 0x00 0x00 这样printf("%d\n",*p); 就只读取了 0x04,0xFF被抛弃了,所以就不一样了。

3.数组指针的初始化

如果要将一块地址空间(也就是针变量里的值置零)进行初始化,一般这么写:

char pstr[20]={NULL}//初始化时这么写,或者是:

memset(pstr,NULL,sizeof(pstr));//代码中这么写,当然也可以是动态分配。

char *pstr = new char[20];//只要记住delete[]回收内存就可以了

4.类指针的初始化

动态分配一个类指针,比如:

A *pA = new A

那么这时一定要保证类中具有构造函数。如果A *pA=0 (好像是调用的默认构造函数吧,这个记得不太清楚了!)

class A{

       public:

       A(){cout<<"A cst"<<endl;} 

       virtual ~A(){cout<<"A decst"<<endl;} 

       void doSomething(){cout<<"a is doing someting"<<endl;}

     };

   

class B:public A{

       public:

       B(){cout<<"B cst"<<endl;} 

       ~B(){cout<<"B decst"<<endl;} 

       //void doSomething(){cout<<"b is doing something"<<endl;}

     };

   

int main()

{

A *aptb;(这里尽然通过编译,显然指针没有指向任何实例)

aptb->doSomething();

system("pause");

return 0;

}

上述例子中并没有错,只是这个习惯不好,如果在其他程序需要通过指针来做赋值操作什么的话,就会出现错误访问了非法内存。一般给指针一个实例只是为了防止访问了非法内存而造成错误。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值