彻底搞定C指针

1. 变量的实质是什么?

变量就是在声明的内存中存放的值,变量的操作通过相应的地址操作来实现。

2. 指针

指针的声明为空,否则容易造成空指针,造成内存泄漏等不安全因素。

指针与数组相关关系:

指针是指针变量,而数组名只是一个指针变量。所以可以有指针的自增操作,而没有数组名的自增操作。但是当指针被定义为const类型之后,便不能进行修改:int const * p;(/* 注意const的位置:不是const int *pa */)

{

const 的用法,const会修饰离他最近的对象。

一个比较经典的问题——问以下两种声明的区别:
1)  const char * p(不能通过*p来修改指向对象的值)
2)  char * const p(不能修改指针的指向,但是可以通过*p来修改值)

但是:

const int p;与 int const p的作用是一样的,在声明变量时其效果是一样的,略微思考,无论是哪个其限制效果是一样了。  


这里的 const 关键字是用于修饰常量,书上说 const 将修饰离它最近的对象,所以,以上两种声明的意思分别应该是:
1)  p 是一个指向常量字符的指针,不变的是 char 的值,即该字符的值在定义时初始化后就不能再改变。
2)  p 是一个指向字符的常量指针,不变的是 p 的值,即该指针不能再指向别的。

 

现在倒是正确说出了两者的意思,但应该怎样记忆它们呢?
至少我觉得我经常会忘记,以后再遇到了可能又会混淆不清。-_- !

 

无意间,在网上看到有人介绍了一种不错的记忆方法,分享如下:

 

Bjarne 在他的《The C++ Programming Language》里面给出过一个助记的方法——“以 * 分界,把一个声明从右向左读”。
注意语法,* 读作 pointer to (指向...的指针),const (常量) 是形容词,char (变量类型) 和 p (变量名) 当然都是名词。 
1)  const char * p 读作:p is a pointer to a const char,译:p 是一个指针(变量),它指向一个常量字符(const char)
2)  char * const p 读作:p is a const pointer to a char,译:p 是一个常量指针(const p),它指向一个字符(变量)。

从两处蓝色标记也能看出前面提到的“const 修饰离开最近的对象”的说法。

 

另外请再注意下面的情况。
先看 const int a 和 int const a,这里没有分界符 *,虽然 const 的位置不同,但意思不变,它 const 修饰的是 int,常量整数。
再看 const char * p 和 char const * p,首先以 * 分界,虽然 const 的位置改变了,但它都是在修饰 char,常量字符。

}

3. 几种参数传递方式

值传递:在函数的哦调用过程中会隐式地把参数的值直接复制给参数,在函数的内部不会对传入的变量进行操作。

地址传递:地址传递与值传递其实没有什么不同,只是其传递的是地址,或者说指针,这样就是说其操作的是地址中的内容。

引用传递:就是用外部的变量代替局部参数变量。

4. 指针的指针

其实,指针在程序的内存中也会像普通的数据一样存储,存放的连续的内存空间内。指针的指针,就是将指针作为变量,指向指针的地址。(指针在32位的操作系统中占用4个字节)

指针型数组的声明:

double*  p[num];其每一个元素均是指针

指针数组的指针:

double**p[num]; (数组指针:int (*p)[10]; p即为指向数组的指针,又称数组指针。注意区分

同时注意指针数组与数组指针的区别,后者是指向数组的首地址

5. 函数指针

函数名是个什么东西呢?这是一个很值得回答的问题,在程序内部调用函数的时候,是什么作为一个入口来调用函数的呢?

原来,就像数据变量的内存地址可以存储在相应的指针变量中一样,函数的首地址也是存储在某个函数指针变量里面的。这样,就可以通过这个函数指针变量来调用所指向的函数。

函数指针的声明:

void (*fun)(int);//其声明是将函数声明形式改成指针的形式。

因此,有这样的指针就可以像数据一样进行操作了,如(*fun)(10)就可以了。

注意函数指针与函数返回指针的区别:

void* fun(int) //此声明是说函数的返回值形式

原来:

  • 函数名和函数指针是一样的,即都是函数指针;
  • 本来函数的调用应该是(*fun)(10),但是C语言的设计者为了调用的方便,所以才设计了fun(10)这样的调用方法,目的是为了同正常函数中的调用方式相似;
  • 为了统一起见,函数指针变量(*fun)也可以fun(10)来调用;
  • 赋值时,即可Fun = &MyFun形式,也可Fun = MyFun。
  • 综上所述,两种方案是通用的,但是声明处还是显示要声明,到底是正常的int myfun(int);还是int (*myfun)(int)需要自己制定。
6. 定义某一函数的指针类型

typedef void (*FunType)(int); /*(★)这样只是定义一个函数指针类型*/
FunType FunP; /*然后用FunType类型来声明全局FunP变量*/

首先,在void (*FunType)(int)前加了一个typedef 。这样只是定义一个名为FunType函数指针类型,而不是一个FunType变量。
然后,“FunType FunP;”这句就如“PINT px;”一样地声明一个FunP变量。

既然函数是可以内部调用,那么函数的指针也可以作为参数进行调用。所以调用的都是函数名。(例子略)







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值