偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

C/C++面試題:void*通常怎么使用?——快手一面

開(kāi)發(fā)
void* 是一種特殊的指針類型,可以指向任何數(shù)據(jù)類型的對(duì)象(或函數(shù))的地址,但它本身不包含任何關(guān)于它所指向?qū)ο箢愋偷男畔ⅰ?/div>

void* 在 C 和 C++ 中被稱為“無(wú)類型指針”或“通用指針”(generic pointer)。它是一種特殊的指針類型,可以指向任何數(shù)據(jù)類型的對(duì)象(或函數(shù))的地址,但它本身不包含任何關(guān)于它所指向?qū)ο箢愋偷男畔ⅰ?/p>

void* 的主要用途和使用方式包括:

1. 通用函數(shù)接口(如內(nèi)存操作函數(shù)):

標(biāo)準(zhǔn)庫(kù)函數(shù)如 malloc, calloc, realloc 返回 void*,因?yàn)樗鼈兎峙涞氖窃純?nèi)存塊,并不知道你打算在這塊內(nèi)存中存儲(chǔ)什么類型的數(shù)據(jù)。你需要將返回的 void* 顯式轉(zhuǎn)換(cast)為你需要的具體指針類型才能使用。

memcpy, memmove, memset 等函數(shù)接受 void* 參數(shù),因?yàn)樗鼈儼醋止?jié)操作內(nèi)存,不關(guān)心實(shí)際的數(shù)據(jù)類型,只需要知道內(nèi)存地址和大小。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
    // 1. malloc example
    int *p_int = (int*)malloc(sizeof(int)); 
    if (p_int == NULL) {
        perror("Failed to allocate memory");
        return 1;
    }
    *p_int = 100;
    printf("Value via p_int: %d\n", *p_int);
    free(p_int); 
    // 2. memcpy example
    char src[] = "Hello";
    char dest[10];
    memcpy(dest, src, strlen(src) + 1);                                         
    printf("Copied string: %s\n", dest);
    return 0;
}

2.實(shí)現(xiàn)泛型數(shù)據(jù)結(jié)構(gòu)和算法 (主要在 C 語(yǔ)言中):

在 C 語(yǔ)言中,沒(méi)有模板(templates)這樣的泛型編程機(jī)制。如果想創(chuàng)建可以存儲(chǔ)任何類型數(shù)據(jù)的列表、樹(shù)、哈希表等,或者編寫可以處理任何類型數(shù)組的排序、搜索算法(如標(biāo)準(zhǔn)庫(kù)的 qsort),void* 是常用的方法。

數(shù)據(jù)結(jié)構(gòu)通常會(huì)存儲(chǔ) void* 指向?qū)嶋H數(shù)據(jù)。

像 qsort 這樣的函數(shù)接受一個(gè) void* 指向數(shù)組基地址,并需要一個(gè)比較函數(shù),該比較函數(shù)也接受兩個(gè) const void* 參數(shù),你需要在比較函數(shù)內(nèi)部將 void* 轉(zhuǎn)換回實(shí)際的數(shù)據(jù)類型指針進(jìn)行比較。

#include <stdio.h>
#include <stdlib.h>
// Comparison function for qsort (sorting integers)
int compare_ints(const void *a, const void *b) {
    int int_a = *((const int*)a); // Cast void* to const int* and dereference
    int int_b = *((const int*)b); // Cast void* to const int* and dereference
    if (int_a < int_b) return -1;
    if (int_a > int_b) return 1;
    return 0;
}
int main() {
    int numbers[] = {5, 2, 8, 1, 9, 4};
    size_t num_count = sizeof(numbers) / sizeof(numbers[0]);
    printf("Before sorting: ");
    for (size_t i = 0; i < num_count; ++i) printf("%d ", numbers[i]);
    printf("\n");
    // Use qsort with void* base address and comparison function
    qsort(numbers, num_count, sizeof(int), compare_ints);
    printf("After sorting: ");
    for (size_t i = 0; i < num_count; ++i) printf("%d ", numbers[i]);
    printf("\n");
    return 0;
}

3.傳遞不透明數(shù)據(jù)指針

在庫(kù)或 API 設(shè)計(jì)中,有時(shí)會(huì)將內(nèi)部結(jié)構(gòu)的指針作為 void* 返回給用戶,用戶不能(也不應(yīng)該)直接操作它,只能將其傳遞回庫(kù)的其他函數(shù)。這隱藏了實(shí)現(xiàn)細(xì)節(jié)。

4.回調(diào)函數(shù)的用戶數(shù)據(jù)(User Data / Context)

許多 API(如圖形庫(kù)、線程庫(kù)、事件處理系統(tǒng))允許你注冊(cè)一個(gè)回調(diào)函數(shù),并在注冊(cè)時(shí)提供一個(gè) void* 參數(shù)(通常稱為 userData、context 或類似名稱)。當(dāng) API 調(diào)用你的回調(diào)函數(shù)時(shí),它會(huì)把你當(dāng)初提供的 void* 再傳回給你的回調(diào)函數(shù)。這允許你的回調(diào)函數(shù)訪問(wèn)特定的上下文信息,而 API 本身無(wú)需知道這些信息的具體類型。

假設(shè)有一個(gè)庫(kù)函數(shù) setTimer,它會(huì)在指定的毫秒數(shù)后調(diào)用你提供的回調(diào)函數(shù)。為了讓你的回調(diào)函數(shù)知道是哪個(gè)計(jì)時(shí)器觸發(fā)了(或者攜帶任何你想傳遞的信息),setTimer 允許你傳遞一個(gè) void* 用戶數(shù)據(jù)。

#include <stdio.h>  // 包含標(biāo)準(zhǔn)輸入輸出頭文件
#include <stdlib.h> // 包含標(biāo)準(zhǔn)庫(kù)頭文件 (用于 NULL)
// --- 假設(shè)這是外部庫(kù)的一部分 ---
typedef void (*TimerCallback)(int timerId, void* userData);
// 模擬設(shè)置一個(gè)定時(shí)器。
void setTimer(int milliseconds, TimerCallback callback, void* userData) {
    printf("定時(shí)器庫(kù):正在設(shè)置 %d 毫秒的定時(shí)器。\n", milliseconds);
    // --- 想象等待 'milliseconds' 毫秒 ---
    printf("定時(shí)器庫(kù):定時(shí)器到期!調(diào)用回調(diào)函數(shù)。\n");
    // 庫(kù)函數(shù)不知道也不關(guān)心 userData 指向什么,
    // 它只是將其原樣傳遞回給回調(diào)函數(shù)。
    int assignedTimerId = 1;
    callback(assignedTimerId, userData); // 調(diào)用回調(diào),傳入ID和用戶數(shù)據(jù)
    printf("定時(shí)器庫(kù):回調(diào)完成。\n");
}
// --- 應(yīng)用程序代碼 ---
// 1. 定義傳遞給回調(diào)函數(shù)的數(shù)據(jù)結(jié)構(gòu)
typedef struct {
    const char* message; // 消息字符串
    int retryCount;      // 重試次數(shù)計(jì)數(shù)器
} MyTimerInfo;
// 2. 實(shí)現(xiàn)匹配 TimerCallback 簽名的回調(diào)函數(shù)
void handleTimerExpiration(int timerId, void* userData) {
    printf("我的應(yīng)用程序:收到定時(shí)器 ID %d 的回調(diào)。\n", timerId);
    // 重要:將 void* 指針強(qiáng)制轉(zhuǎn)換回正確的指針類型 (MyTimerInfo*)
    MyTimerInfo* info = (MyTimerInfo*)userData;
    printf("消息: %s, 重試次數(shù): %d\n", info->message, info->retryCount);
    info->retryCount++; // 修改數(shù)據(jù)
}
// 3. 主邏輯中,創(chuàng)建數(shù)據(jù)并注冊(cè)定時(shí)器
int main() {
    MyTimerInfo myInfo;
    myInfo.message = "任務(wù) A 需要處理";
    myInfo.retryCount = 0;
    printf("我的應(yīng)用程序:正在注冊(cè)定時(shí)器...\n");
    setTimer(1000, handleTimerExpiration, &myInfo); // 傳遞 myInfo 的地址
    printf("我的應(yīng)用程序:定時(shí)器注冊(cè)調(diào)用完成。\n");
    // 打印修改后的重試次數(shù),驗(yàn)證回調(diào)函數(shù)確實(shí)修改了它
    printf("我的應(yīng)用程序:當(dāng)前重試次數(shù) (回調(diào)之后): %d\n", myInfo.retryCount);
    return 0; // 程序正常退出
}

5.重要注意事項(xiàng)

  • 不能直接解引用 : 你不能直接對(duì) void* 使用 * 運(yùn)算符,因?yàn)榫幾g器不知道它指向的數(shù)據(jù)類型有多大,以及如何解釋這些字節(jié)。
  • 必須顯式轉(zhuǎn)換: 在使用 void* 指向的數(shù)據(jù)之前,必須將其顯式轉(zhuǎn)換(cast)為正確的具體數(shù)據(jù)類型指針。
  • 類型安全: void* 的使用會(huì)繞過(guò)編譯器的類型檢查。如果你將 void* 轉(zhuǎn)換回了錯(cuò)誤的類型,會(huì)導(dǎo)致未定義行為(Undefined Behavior),通常是程序崩潰或數(shù)據(jù)損壞。這是 void* 的主要缺點(diǎn)。
  • 指針運(yùn)算: 不能對(duì) void* 進(jìn)行指針?biāo)阈g(shù)運(yùn)算(如 ptr++ 或 ptr + 1),因?yàn)榫幾g器不知道每個(gè)元素的大小。 (GCC 等編譯器可能有擴(kuò)展允許,但不標(biāo)準(zhǔn)且危險(xiǎn))。
  • C++ 中的替代方案: 在 C++ 中,雖然 void* 仍然可用且在與 C 庫(kù)交互時(shí)必不可少,但對(duì)于泛型編程,通常推薦使用模板(templates),它們提供了類型安全。對(duì)于類型轉(zhuǎn)換,C++ 提供了更安全的轉(zhuǎn)換運(yùn)算符,如 static_cast, dynamic_cast, 和 reinterpret_cast。reinterpret_cast<T*>(void_ptr) 常用于 void* 和其他指針類型之間的轉(zhuǎn)換,但同樣需要開(kāi)發(fā)者保證類型轉(zhuǎn)換的正確性。

void* 是一個(gè)強(qiáng)大的工具,用于實(shí)現(xiàn)通用性,但犧牲了類型安全。使用它時(shí),必須非常小心,確保在解引用或操作指針之前,總是將其轉(zhuǎn)換回正確的原始類型。

責(zé)任編輯:趙寧寧 來(lái)源: CppPlayer
相關(guān)推薦

2025-08-18 02:11:00

2025-05-20 10:00:00

C++命名空間別名代碼

2021-10-27 11:00:30

C++語(yǔ)言面試

2025-05-23 08:15:00

C++constexpr字面類型

2025-08-26 02:15:00

C++函數(shù)Student

2025-08-11 05:00:00

2010-02-06 09:59:54

C++ void使用規(guī)

2025-08-18 02:12:00

2025-05-26 03:20:00

2025-04-30 10:10:00

在 C++C++11Lambda

2011-03-29 14:31:41

CC++

2025-03-24 07:35:00

開(kāi)發(fā)注解Spring

2025-08-28 09:21:25

2025-05-06 08:20:00

互斥鎖C++編程

2025-08-13 01:00:00

2010-02-06 09:53:26

C++ void

2009-08-11 14:59:57

一道面試題C#算法

2025-09-29 01:15:00

2025-05-20 08:10:00

函數(shù)函數(shù)類型函數(shù)指針類型

2025-06-05 08:05:00

vectorC++對(duì)象存儲(chǔ)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)