理解C语言中的void类型的指针

发布时间 2023-09-22 23:20:24作者: Guanjie255

1.void类型指针简介

  • void类型的指针又被称为泛型指针,通用型指针
  • void类型的指针:指针指向的内存地址中的数据的类型未知
  • 其他所有类型的指针都可以转换为void类型的指针,而且不需要强制类型转换(编译器会隐式/自动类型转换)
  • void类型的指针也可以转换为任意类型的指针,需要强制类型转换(实际上不需要,但是强制类型转换会增加代码的可读性,比如使用malloc函数的时候)
  • void类型的指针不可以直接解引用(dereference),强制类型转换之后才可以正常访问void指针指向的内存单元
int main() {
  int a = 10;
  // 指针p指向变量a, 但是p的类型仍然是void
  void* p = &a;
  printf("%d\n", *p);  // 错误,因为p是void类型的,编译器无法判断p可以访问几个字节
  printf("%d\n", *(int*)p);  // 正确,将p强制转换为int类型的指针,编译器就指导p指向的数据占用四个字节
  return 0;
}

2.探讨void类型指针为什么具有通用性?

2.1 以以下代码为例,通过void类型的指针p,可以正常访问不同类型的变量,因此,void类型的指针被成为泛型指针/通用型指针

2.2 除了void类型的指针之外,其他类型的指针不可以实现这种特性

#include <stdio.h>

int main(int argc, char* argv[]) {
  char a = 'H';
  int b = 10;
  float c = 2.8;
  double d = 9.7;
  void* p;
  
  // p saves the address of variable a
  p = &a;
  printf("a = %c\n", *(char*)p);
  
  // p saves the address of variable b
  p = &b;
  printf("b = %d\n", *(int*)p);
  
  // p saves the address of variable c
  p = &c;
  printf("c = %f\n", *(float*)p);
  
  // p saves the address of variable d
  p = &d;
  printf("d = %lf\n", *(double*)p);
  return 0;
}

3.void指针的应用:使用一个泛型指针可以遍历不同类型的数组!

#include <stdio.h>
enum type {
 CHAR,
 INT,
 DOUBLE
};

void generic_function(enum type t, void* ptr);

int main(int argc, char* argv[]) {
  // void type pointer / generic pointer / general-purpose pointer
  char ch_arr[] = "Hello";
  int int_arr[] = {3, 1, 2};
  double db_arr[] = {3.14, 2.7, 1.58, 20.4};
  
  // print the first element for each different type array
  generic_function(CHAR, ch_arr);
  generic_function(INT, int_arr);
  generic_function(DOUBLE, db_arr);
  
  return 0;
}

void generic_function(enum type t, void* ptr) {
  // t的类型指导泛型指针ptr如何访问数组(强制类型转换不同)
  switch(t) {
    case CHAR:
      printf("The first element is: %c\n", ((char*)ptr)[0]);
      break;
    case INT:
      printf("The first element is: %d\n", ((int*)ptr)[0]);
      break;
    case DOUBLE:
      printf("The first element is: %lf\n", ((double*)ptr)[0]);
      break;
    default:
      printf("No type matched!\n");
  }  
  
}