void与null

青旅半醒 2023-07-11 06:28 71阅读 0赞

void

void一般用在两种情况下。第一种情况是,如果函数没有返回值或参数,那么应该声明为void,不同的编译器会对省略的定义有所不同的解释,这种显示的定义明显可以提高程序的平台移植性。例如下面定义了一个没有传入参数、没有返回值的一个函数void func(void)。如果返回值得类型不用void指定,有的编译器会默认返回得是一个int类型,这样就会造成一些潜在得移植错误。

第二种使用void得情况是声明一个void类型得指针:void* vp。对于void类型指针,它只保存一个地址,不包含指向变量的类型信息,所以任何类型的指针都可以直接赋值给它,无需进行强制类型转换。

void类型指针一般用在函数的参数和返回之中,以达到泛型的目的,目的就是使一个函数能够处理更多的类型。例如malloc函数就返回一个void类型指针,同理,memcpy和memset两个函数也使用void类型指针来达到泛型的目的。这样,任何类型的指针都可以传入memcpy和memset中,这也真实体现了内存操作函数的意义,因为它操作的对象仅仅是一块内存,并不关心这块内存中保存的是什么类型。

  1. void * malloc(size_t size);
  2. void * memcpy(void *dest, const void *src, size_t len);
  3. void * memset(void * buffer, int c, size_t num);

void类型指针虽然可以用来达到泛型的目的,但是它也包含一些风险,这种风险主要是丢失了类型的信息。如果有类型信息,编译器可以帮助我们进行类型匹配检查。下面程序中把一个int型的指针赋值给一个float类型,类型并不匹配,所以编译并不会通过。

  1. void test(int* pi)
  2. {
  3. float *pf = pi; // 编译出错
  4. }
  5. int i = 5;
  6. test(&i);

当你把int型地址复制给void类型指针,类型信息丢失了。在test2函数内部,当你把void类型强制转换成float类型的指针时,编译器并不进行任何类型匹配的检查。编译通过,但是pf指针指向的地址并不包含你期望的浮点数,所以往往会产生一些奇怪的错误。

  1. void test2(void* pi)
  2. {
  3. float *pf = (float*)pi; // 编译通过
  4. }
  5. int i = 5;
  6. test2(&i);

NULL

与void类型指针不同,NULL不是指针的类型,而是用来描述指针的值。一般情况下NULL被定义为0。如果定义int *p = NULL;的话,就意味着p没有指向任何地址。这样就是安全的,NULL对暂时不用的指针变量赋初值,以避免产生野指针的问题。NULL也用在一些函数的返回中,如果返回的是NULL,那么就代表函数调用并没有返回成功,如fopen函数以及fgets函数等等。

发表评论

表情:
评论列表 (有 0 条评论,71人围观)

还没有评论,来说两句吧...

相关阅读

    相关 voidnull

    void void一般用在两种情况下。第一种情况是,如果函数没有返回值或参数,那么应该声明为void,不同的编译器会对省略的定义有所不同的解释,这种显示的定义明显可以提高