01 February 2015

NULL 在C语言中定义为:

#define NULL ((void *)0) 把地址0转换成指针类型,称为空指针

它的特殊之处在于,操作系统不会把任何数据保存在地址0及其附近,也不会把地址0~0xfff的页面映射到物理内存,所有对地址0的访问都会立刻导致段错误

*p=0会导致段错误,就像放在眼前的炸弹一样很容易找到,相比之下,野指针的错误就像埋下地雷一样,更难发现和排除,这次走没事,下次走就有事

void *指针与其他类型的指针之间可以隐式的转换,而不必用类型转换运算符。注意,只能定义void *指针,而不能定义void型的变量,因为void *型指针和别的指针一样都占4个字节,而如果定义void型的变量,编译器不知道该分配几个字节给变量。

void *指针不能直接Dereference(指针所指的值),而必须先转换成别的类型的指针在做Dereference。

void func(void *pv)
{
    /*  *pv ='A' is illegal */
    char *pchar = pv;
    *pchar = 'A';
}

int main(void)
{
    char c;
    func(&c);      //传递的只能是指针
}

void指针使用规范

  • void指针可以指向任意类型的数据,亦可用任意数据类型指针对void指针赋值,例如
int *print;
void *pvoid;
pvoid = print;
print = (int *)pvoid;    //在将pvoid赋给其他类型的指针时需要强制类型转换
  • void 函数参数和函数返回进行限定

    • 当函数不需要返回值时,必须使用void,void func(int,int);
    • 当函数不接受参数时,必须使用void,int func(void);
    • void*可以指向任意类型的数据,因此可以用void*作为函数形参,这样的函数可以接受任意类型数据的指针作为参数:void *memcpy(void *dest,const void *src,size_t len);
  • 当要访问void指针的值时,需要将其强制转为其他类型才能访问,因为它表示的内存地址,不能直接访问

函数指针

对于一个函数而言,函数名也是指向函数第一条指令的常量指针。而编译器要做的就是在程序编译之后,为每个函数分配一个首地址,即该函数第一条指令的地址。一般情况下,我们可以用一个指针来保存这个地址,而这个指针就是函数指针,该指针可以看作是它指向函数的别名,所以我们可以用该指针来调用这个函数。

type (*func)(type &, type &) 此语句声明一个指针func,它指向一个函数,函数带两个type型参数并返回一个type值

  • 一个指向函数的指针必须确保被定义且分配了内存,否则它将指向一个空地址
  • 特别注意第一个括号位置,如果我们不写括号: type *func(type,type),这就不是一个指向函数的指针了,而是声明了一个函数,该函数返回一个type类型的指针

例子:


int max(int a,int b) 
{
    return a>b?a:b;
}
int min(int a,int b)
{
    return a<b?a:b;
}
int (*func)(int,int);    //声明函数指针,指向返回类型为int
int main()
{
    func = max;
    int c = (*func)(1,2);
    func = min;
    c = (*func)(1,2);
}

说明:func是一个函数指针,那么func就是指向该指针所指向的函数地址,所有(*func)(int,int)就是调用该函数的方式,ANSI C标准允许程序员将上式简写为func(),但是一定要记住这种写法只是一种简写形式

在表达式(func)()中,func两侧的括号很重要的

  • func 是一个函数指针
  • func()是(*func)()的简写形式
  • &func是&(*func)的简写形式