HOWTO · C

使用 C 語言中的 strdup 函式

了解 strdup 如何在 C 語言中複製字串、如何檢查並釋放其分配的副本,以及何時使用 strndup 或 GNU 的 strdupa。

本頁內容

strdup 會建立以 null 字元結尾的 C 字串副本,並回傳另外配置的記憶體。使用前請先檢查回傳的指標,成功取得副本後則以 free 釋放。若要限制複製的位元組數,請使用 strndup;strdupa 是 GNU 專用的替代方案,其記憶體生命週期不同。

strdup 的用途與可用性

strdup 的宣告為 char *strdup(const char *s);,位於 <string.h>。它會將以 null 字元結尾的字串 s 複製到新配置的儲存空間,包含結尾的 null 字元。回傳的指標指向這塊儲存空間;若配置失敗,函式會回傳 NULL。

strdup 不屬於 C 標準函式庫。它由 POSIX 規範定義,也由 GNU C 函式庫等常見 C 函式庫提供。在嚴格語言模式下編譯時,某些平台可能需要功能測試巨集,才能公開這項宣告。若需要在 POSIX 系統以外的平台維持可攜性,請查閱目標平台的文件。

使用 strdup 複製字串

若平台使用 _POSIX_C_SOURCE 公開 POSIX 宣告,請在引入標頭檔前定義此巨集。範例會先檢查結果再讀取副本,並在使用後釋放副本。成功執行時,程式會印出來源字串及其副本。

執行此範例:

#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    const char *source = "C strings";
    char *copy = strdup(source);

    if (copy == NULL) {
        puts("Could not duplicate the string.");
        return EXIT_FAILURE;
    }

    printf("Source: %s\nCopy: %s\n", source, copy);
    free(copy);
    return 0;
}
Source: C strings
Copy: C strings

如果 strdup 回傳 NULL,請勿將該指標傳給字串函式,也不要對它呼叫 free。上方的失敗分支會回報問題並正常結束程式。副本不再需要時,請呼叫一次 free 釋放它;釋放來源字串常值,或在副本釋放後繼續使用,都不是有效的操作。

使用 strndup 最多複製 n 個位元組

strndup 同樣由 POSIX 規範定義,並在 <string.h> 中宣告。其宣告為 char *strndup(const char *s, size_t n);。它會從 s 複製至多 n 個位元組,並在配置所得的結果末尾加上 null 字元。這個限制計算的是位元組而非字元,因此若限制落在多位元組編碼字元的中間,該字元可能只複製到一部分。

例如,strndup("C strings", 3) 會產生字串 "C s"。回傳的儲存空間是動態配置的,因此請檢查結果是否為 NULL,並像使用 strdup 一樣,以 free 釋放成功取得的結果。這項限制只控制複製的長度,不會改變結果的生命週期或所有權。

認識 GNU 專用的 strdupa 替代方案

strdupa 是 GNU C 函式庫的擴充功能,不是 POSIX 或標準 C 函式。若需要公開其宣告,請在系統標頭檔之前定義 _GNU_SOURCE。與 strdup 一樣,它接受以 null 字元結尾的字串並建立副本,但使用的是與目前函式相關的自動儲存空間,而非堆積配置。

這塊儲存空間只會在所在函式執行期間存在。請勿回傳該指標並在函式結束後使用,也不要將它傳給 free。strdupa 的可用性與實作取決於 GNU 環境;若需要 POSIX 介面,或需要自行透過 free 控制副本的生命週期,請使用 strdup。此處不提供 strdupa 的可執行範例,因為它僅適用於 GNU 環境。