ตัวชี้ไปยังvoid
เป็นประเภทตัวชี้ "ทั่วไป" void *
สามารถแปลงเป็นตัวชี้ประเภทอื่น ๆ ได้โดยไม่ต้องหล่ออย่างชัดเจน คุณไม่สามารถอ้างถึง a void *
หรือ do การคำนวณทางคณิตศาสตร์ด้วย; คุณต้องแปลงเป็นตัวชี้ไปยังชนิดข้อมูลที่สมบูรณ์ก่อน
void *
มักใช้ในสถานที่ที่คุณต้องทำงานกับตัวชี้ชนิดต่าง ๆ ในรหัสเดียวกัน ตัวอย่างหนึ่งที่อ้างถึงโดยทั่วไปคือฟังก์ชั่นห้องสมุดqsort
:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
base
คือที่อยู่ของอาเรย์nmemb
คือจำนวนองค์ประกอบในอาเรย์size
เป็นขนาดของแต่ละองค์ประกอบและcompar
เป็นตัวชี้ไปยังฟังก์ชันที่เปรียบเทียบสององค์ประกอบของอาเรย์ มันถูกเรียกเช่น:
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);
นิพจน์อาร์เรย์iArr
, dArr
และlArr
จะถูกแปลงโดยปริยายจากประเภทอาร์เรย์ชนิดชี้ในการเรียกใช้ฟังก์ชันและแต่ละคนจะถูกแปลงโดยปริยายจาก "ชี้ไปint
/ double
/ long
" เป็น "ตัวชี้ไปvoid
"
ฟังก์ชันเปรียบเทียบจะมีลักษณะดังนี้:
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;
}
โดยการยอมรับvoid *
, qsort
สามารถทำงานกับอาร์เรย์ของชนิดใด ๆ
ข้อเสียของการใช้void *
คือคุณโยนความปลอดภัยประเภทนอกหน้าต่างและเป็นการจราจรที่กำลังจะมาถึง ไม่มีอะไรที่จะปกป้องคุณจากการใช้รูทีนการเปรียบเทียบที่ไม่ถูกต้อง:
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareInt
คาดว่าข้อโต้แย้งของมันจะชี้ไปที่int
s แต่จริงๆแล้วทำงานกับdouble
s ไม่มีทางที่จะจับปัญหานี้ในเวลารวบรวม; คุณจะจบลงด้วยอาเรย์ที่ถูกพลาด