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)需要自己制定。
typedef void (*FunType)(int); /*(★)这样只是定义一个函数指针类型*/
FunType FunP; /*然后用FunType类型来声明全局FunP变量*/
首先,在void (*FunType)(int)前加了一个typedef 。这样只是定义一个名为FunType函数指针类型,而不是一个FunType变量。
然后,“FunType FunP;”这句就如“PINT px;”一样地声明一个FunP变量。
既然函数是可以内部调用,那么函数的指针也可以作为参数进行调用。所以调用的都是函数名。(例子略)