【C語言基礎】雙指針在qsort函數中的應用

在C語言中使用 qsort 對字符串數組(如 char* 數組)排序時,必須轉換為雙指針(char**,這是由字符串數組的內存結構和 qsort 的工作原理決定的。以下是詳細解釋:


一、底層原理分析

1. 字符串數組的內存結構

假設有一個字符串數組:

char* strs[] = {"apple", "banana", "cherry"};

其內存布局如下:

strs[0] → 指向 "apple" 的首地址
strs[1] → 指向 "banana" 的首地址
strs[2] → 指向 "cherry" 的首地址

每個元素 strs[i] 的類型是 char*(字符串指針),因此:

  • 數組名 strs 的類型是 char**(指向指針的指針)
  • qsort 傳遞給比較函數的是 strs[i] 的地址(即 &strs[i]),其類型為 char**

2. qsort 的比較函數參數

qsort 的比較函數原型為:

int compar(const void *a, const void *b);
  • 參數 ab 是數組元素的指針,即 &strs[i]&strs[j]
  • 對于字符串數組,ab 的類型是 char**(指針的指針)。

二、正確轉換步驟

1. 錯誤寫法(直接轉 char*
// 錯誤!會導致比較的是字符串內容,而非指針地址
int compare_strings_wrong(const void *a, const void *b) {const char *str1 = (const char*)a; // ? 直接轉換const char *str2 = (const char*)b;return strcmp(str1, str2);
}
  • 問題ab 本質是 &strs[i]char** 類型),若直接轉為 char*,實際比較的是指針地址值,而非字符串內容。

2. 正確寫法(轉雙指針后解引用)
int compare_strings(const void *a, const void *b) {const char **str1 = (const char **)a; // ? 轉換為雙指針const char **str2 = (const char **)b;return strcmp(*str1, *str2); // 解引用得到實際的字符串指針
}
  • 關鍵點
    • a/b 轉為 char**(因為它們本質是 char** 類型)
    • 解引用(*str1)得到實際的 char*(字符串首地址)
    • 比較字符串內容而非指針地址。

三、類比其他類型

int 數組為例:

int arr[] = {5, 2, 8};
  • 比較函數的參數是 int*(數組元素地址),直接解引用即可:
int compare_ints(const void *a, const void *b) {int num1 = *(const int*)a; // ? 直接轉 int*int num2 = *(const int*)b;return num1 - num2;
}
  • 字符串數組與之不同,因為數組元素本身是指針(char*),所以需要多一層解引用。

四、常見錯誤場景

1. 錯誤結果示例

若錯誤地直接轉換:

const char *str1 = (const char*)a; // a 是 char**,轉 char* 后值等于 &strs[i]
const char *str2 = (const char*)b;
  • str1 的值是 &strs[i](即 char** 的地址值)
  • strcmp(str1, str2) 會比較這兩個地址值的 ASCII 碼,而非字符串內容,導致排序混亂。

2. 內存訪問崩潰

若字符串數組元素為 NULL

char* strs[] = {"apple", NULL, "cherry"};
  • 錯誤轉換后,strcmp 會嘗試訪問 NULL 地址,導致段錯誤。

五、總結

數據類型qsort 參數類型比較函數轉換方式
int[]int*(指向元素的指針)*(const int*)a
char*[]char**(指向指針的指針)*(const char**)a

核心原則qsort 始終傳遞數組元素的地址,需根據元素類型決定如何轉換和解引用。

以下是引用

逐步解釋

  1. 定義比較函數

    int compare_strings(const void *a, const void *b) {const char **str1 = (const char **)a;const char **str2 = (const char **)b;return strcmp(*str1, *str2);
    }
    
    • const void *aconst void *bqsort 傳遞給比較函數的參數。
    • const char **str1const char **str2 是將 const void* 轉換為 const char** 后的結果。
    • *str1*str2 分別是 str1str2 指向的字符串。
  2. 調用 qsort

    qsort(strs, len, sizeof(char*), compare_strings);
    
    • strs 是要排序的數組。
    • len 是數組的長度。
    • sizeof(char*) 是每個元素的大小(即每個元素是指針)。
    • compare_strings 是比較函數。
  3. 輸出排序后的結果

    for (size_t i = 0; i < len; i++) {printf("%s ", strs[i]);
    }
    printf("\n");
    

為什么需要雙指針轉換

  • 第一次轉換:將 const void* 轉換為 const char**,因為 qsort 傳遞的是指向數組元素的指針。
  • 第二次轉換:通過 *str1*str2 獲取實際的字符串指針,以便使用 strcmp 函數進行比較。

通過這種方式,我們可以正確地對字符串數組進行排序,而不會出現類型不匹配的問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/76987.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/76987.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/76987.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

批處理(Batch Processing)的詳解、流程及框架/工具的詳細對比

以下是批處理&#xff08;Batch Processing&#xff09;的詳解、流程及框架/工具的詳細對比&#xff1a; 一、批處理核心概念 定義&#xff1a; 批處理是離線處理大量數據或任務的自動化流程&#xff0c;特點是無人值守、高吞吐量、資源密集型&#xff0c;常用于數據清洗、報表…

基于FreeRTOS和LVGL的多功能低功耗智能手表(APP篇)

目錄 一、簡介 二、軟件框架 2.1 MDK工程架構 2.2 CubeMX框架 2.3 板載驅動BSP 1、LCD驅動 2、各個I2C傳感器驅動 3、硬件看門狗驅動 4、按鍵驅動 5、KT6328藍牙驅動 2.4 管理函數 2.4.1 StrCalculate.c 計算器管理函數 2.4.2 硬件訪問機制-HWDataAccess 2.4.3 …

【初階數據結構】——算法復雜度

一、前言 1、數據結構是什么&#xff1f; 數據結構(Data Structure)是計算機存儲、組織數據的?式&#xff0c;指相互之間存在?種或多種特定關系的數 據元素的集合。沒有?種單?的數據結構對所有?途都有?&#xff0c;所以我們要學各式各樣的數據結構&#xff0c; 如&…

記錄 | Pycharm中如何調用Anaconda的虛擬環境

目錄 前言一、步驟Step1 查看anaconda 環境名Step2 Python項目編譯器更改 更新時間 前言 參考文章&#xff1a; 參考視頻&#xff1a;如何在pycharm中使用Anaconda創建的python環境 自己的感想 這里使用的Pycharm 2024專業版的。我所使用的Pycharm專業版位置&#xff1a;【僅用…

linux如何用關鍵字搜索日志

在 Linux 系統中搜索日志是日常運維的重要工作&#xff0c;以下是幾種常用的關鍵字搜索日志方法&#xff1a; 1. 基礎 grep 搜索 bash 復制 # 基本搜索&#xff08;區分大小寫&#xff09; grep "keyword" /var/log/syslog# 忽略大小寫搜索 grep -i "error&…

K-均值聚類機器學習算法的優缺點

K-均值聚類是一種常用的無監督學習算法&#xff0c;用于將具有相似特征的數據點聚集到一起。以下是K-均值聚類算法的步驟及其優缺點&#xff1a; K-均值聚類算法步驟&#xff1a; 初始化&#xff1a;隨機選擇K個點作為初始的聚類中心。分配數據點&#xff1a;將每個數據點分配…

AI驅動SEO關鍵詞實戰策略

內容概要 AI驅動的SEO關鍵詞優化體系通過技術融合實現了策略升級。該框架以語義理解模型為基礎&#xff0c;結合實時流量監測與行業數據庫&#xff0c;構建了包含關鍵詞挖掘、競爭評估、內容適配三大核心模塊的閉環系統。通過自然語言處理&#xff08;NLP&#xff09;技術解析…

Golang|在線排查協程泄漏

根據我們的代碼&#xff0c;前5毫秒內&#xff0c;每隔1毫秒就會來一個請求&#xff0c;5毫秒之后由于前面的協程執行完&#xff0c;后面又會來新的協程&#xff0c;所以協程數目會保持穩定但是代碼一運行&#xff0c;協程數量一直增長&#xff0c;發生了協程泄漏 我們可以list…

Java項目之基于ssm的QQ村旅游網站的設計(源碼+文檔)

項目簡介 QQ村旅游網站實現了以下功能&#xff1a; 管理員權限操作的功能包括管理景點路線&#xff0c;板塊信息&#xff0c;留言板信息&#xff0c;旅游景點信息&#xff0c;酒店信息&#xff0c;對景點留言&#xff0c;景點路線留言以及酒店留言信息等進行回復&#xff0c;…

高級語言調用C接口(四)結構體(2)-Python

這個專欄好久沒有更新了&#xff0c;主要是坑開的有點大&#xff0c;也不知道怎么填&#xff0c;涉及到的開發語言比較多&#xff0c;寫起來比較累&#xff0c;需要看的人其實并不多&#xff0c;只能說&#xff0c;慢慢填吧&#xff0c;中間肯定還會插很多別的東西&#xff0c;…

JAVA 主流微服務常用框架及簡介

Java微服務架構的優勢在于其輕量級、高效資源利用&#xff0c;支持快速開發與靈活部署&#xff0c;擁有強大的生態系統與跨平臺兼容性&#xff0c;能夠實現高性能與穩定性&#xff0c;并允許獨立擴展與技術棧多樣性。然而&#xff0c;其劣勢也不容忽視&#xff0c;包括架構復雜…

兒童后期至青少年早期腦網絡隔離增強的發育機制研究

目錄 1 研究背景 2 研究方法 2.1 縱向數據集 2.2 圖像預處理 2.3 個體化區域放射組學相似網絡構建 2.4 分離度&#xff08;模塊化&#xff09;度量 2.5 分離度指數發育變化的建模 2.6 分離指數與認知表現的相關性分析 2.7 成像轉錄組分析 3 研究結果 3.1 三個尺度上…

redis 內存中放哪些數據?

在 Java 開發中,Redis 作為高性能內存數據庫,通常用于存儲高頻訪問、低延遲要求、短期有效或需要原子操作的數據。以下是 Redis 內存中常見的數據類型及對應的使用場景,適合面試回答: 1. 緩存數據(高頻訪問,降低數據庫壓力) 用戶會話(Session):存儲用戶登錄狀態、臨時…

Spring AOP 學習筆記 之 Advice詳解

學習材料&#xff1a;https://docs.spring.io/spring-framework/reference/core/aop/ataspectj/advice.html 1. 什么是 Advice&#xff08;通知&#xff09; 定義&#xff1a;Advice 是 AOP 的核心概念之一&#xff0c;表示在特定的連接點&#xff08;Join Point&#xff09;上…

數智讀書筆記系列029 《代數大腦:揭秘智能背后的邏輯》

《代數大腦:揭秘智能背后的邏輯》書籍簡介 作者簡介 加里F. 馬庫斯(Gary F. Marcus)是紐約大學心理學榮休教授、人工智能企業家,曾創立Geometric Intelligence(后被Uber收購)和Robust.AI公司。他在神經科學、語言學和人工智能領域發表了大量論文,并著有《重啟AI》等多部…

如何看電腦的具體配置?

李升偉 整理 要查看電腦的具體配置&#xff0c;可以通過系統工具、命令行工具或第三方軟件實現&#xff0c;以下是具體方法&#xff1a; 一、系統自帶工具查看&#xff08;無需安裝軟件&#xff09; Windows系統&#xff1a; 系統設置&#xff1a; 右鍵點擊桌面“此電腦”…

開源TTS項目GPT-SoVITS,支持跨語言合成、支持多語言~

簡介 GPT-SoVITS 是一個開源的文本轉語音&#xff08;TTS&#xff09;項目&#xff0c;旨在通過少量語音數據實現高質量的語音合成。其核心理念是將基于變換器的模型&#xff08;如 GPT&#xff09;與語音合成技術&#xff08;如 SoVITS&#xff0c;可能指“唱歌語音合成”&am…

D1084低功耗LDO穩壓器:技術解析與應用設計

引言 在現代電子設計中&#xff0c;低功耗和高效率是至關重要的。D1084是一款5A低功耗低壓差線性穩壓器&#xff08;LDO&#xff09;&#xff0c;以其出色的負載調節能力和快速瞬態響應&#xff0c;成為低電壓微處理器應用的理想選擇。本文將深入解析D1084的技術特性和應用設計…

Log4j詳解:Java日志系統全指南

文章目錄 1. 日志系統簡介1.1 什么是日志1.2 為什么使用日志框架1.3 Java中的常見日志框架 2. Log4j概述2.1 Log4j簡介2.2 Log4j的版本歷史2.3 Log4j與Log4j 2的主要區別 3. Log4j架構與核心組件3.1 Logger&#xff08;日志記錄器&#xff09;3.2 日志級別&#xff08;Level&am…

【信息系統項目管理師】高分論文:論信息系統項目的整合管理(銀行數據倉庫項目)

更多內容請見: 備考信息系統項目管理師-專欄介紹和目錄 文章目錄 正文一、制定項目章程二、制定項目管理計劃三、指導和管理項目的實施四、管理項目知識五、監控項目工作六、實施整體變更控制七、結束項目或階段正文 2023年6月,我以項目經理的身份,參加了 xx銀行xx省分行數…