Friday, January 7, 2022

[c] void*

 A pointer to void is a "generic" pointer type. A void * can be converted to any other pointer type without an explicit cast. You cannot dereference a void * or do pointer arithmetic with it; you must convert it to a pointer to a complete data type first.


void * is often used in places where you need to be able to work with different pointer types in the same code. One commonly cited example is the library function qsort:

==========================================================

void qsort(void *base, size_t nmemb, size_t size, 

           int (*compar)(const void *, const void *));

==========================================================

base is the address of an array, nmemb is the number of elements in the array, size is the size of each element, and compar is a pointer to a function that compares two elements of the array. It gets called like so:

==========================================================

int iArr[10];

double dArr[30];

long lArr[50];

...

qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);

qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);

qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);

==========================================================

The array expressions iArr, dArr, and lArr are implicitly converted from array types to pointer types in the function call, and each is implicitly converted from "pointer to int/double/long" to "pointer to void".


The comparison functions would look something like:

==========================================================

int compareInt(const void *lhs, const void *rhs)

{

  const int *x = lhs;  // convert void * to int * by assignment

  const int *y = rhs;


  if (*x > *y) return 1;

  if (*x == *y) return 0;

  return -1;

}

==========================================================

By accepting void *, qsort can work with arrays of any type.


The disadvantage of using void * is that you throw type safety out the window and into oncoming traffic. There's nothing to protect you from using the wrong comparison routine:

==========================================================

qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);

==========================================================

compareInt is expecting its arguments to be pointing to ints, but is actually working with doubles. There's no way to catch this problem at compile time; you'll just wind up with a missorted array.

example:


/******************************************************************************


Welcome to GDB Online.

GDB online is an online compiler and debugger tool for C, C++, Python, PHP, Ruby, 

C#, VB, Perl, Swift, Prolog, Javascript, Pascal, HTML, CSS, JS

Code, Compile, Run and Debug online from anywhere in world.


*******************************************************************************/

#include <stdio.h>


typedef struct

{

  int one;

  int two;

  int three;

} myStruct2;


typedef struct

{

  int one;

  int two;

} myStruct;


int

main ()

{

  void *a = (void *) sizeof (myStruct2);

  char *b = (char *)a;

  printf ("a :%p\n", a);

  b = b + sizeof (myStruct);

  printf ("b :%p\n", b);


  // Print the sizeof integer

  printf("Size of (void*) = %lu"

           " bytes\n",

           sizeof(void*));

  

  // Print the size of (int*)

  printf("Size of (char*) = %lu"

           " bytes\n",

           sizeof(char*));

  

return 0;

}

a :0xc
b :0x14
Size of (void*) = 8 bytes
Size of (char*) = 8 bytes

void体现了一种抽象,这个世界上的变量都是"有类型"的。void的出现只是为了一种抽象的需要,如果你正确地理解了面向对象中"抽象基类"的概念,也很容易理解void数据类型。

No comments:

Post a Comment

n8n index

 【n8n免費本地端部署】Windows版|程式安裝x指令大補帖  【一鍵安裝 n8n】圖文教學,獲得無限額度自動化工具&限時免費升級企業版功能