使用 C 語言的 setenv 函式訪問環境變數

Jinku Hu 2023年1月30日 2021年2月28日
  1. 在 C 語言中使用 setenv 函式匯出環境變數
  2. 使用 envp 變數在 C 語言中遍歷定義的環境變數
  3. 使用 environ 變數在 C 語言中遍歷定義的環境變數
使用 C 語言的 setenv 函式訪問環境變數

本文將介紹在 C 語言中使用 setenv 函式匯出環境變數的幾種方法。

在 C 語言中使用 setenv 函式匯出環境變數

在 Unix-base 系統上執行的每個程式都有一個環境,它收集了主要由 shell 和其他使用者空間程式使用的變數值對。程式可以用 getenv 函式檢索單個環境變數及其值。但如果要定義一個新的變數或改變現有的變數,則應呼叫 setenv 函式。它需要三個引數,第一個和第二個引數是 char 指標,分別指向變數名和它的值。第三個引數的型別是 int,它指定如果環境中已經存在給定變數的值是否應該被覆蓋。這個引數的非零值表示覆蓋行為,零值表示相反。

但請注意,遍歷所有定義的環境變數,需要訪問名為-environ 的特殊全域性變數,它是一個以 NULL 結尾的字串陣列。另外,也可以宣告 main 函式,第三個引數 envp 來訪問變數。在下面的例子中,我們在呼叫 setenv 函式之前和之後同時列印 enironenvp 指標。請注意,呼叫後,envp 指標的值是一樣的,而 environ 的值已經改變了。

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

int main(int argc, const char *argv[], const char *envp[]) {

    printf("environ:  %p\n", environ);
    printf("envp:     %p\n", envp);

    setenv("NEW_VAR", "new_value", 1);

    puts("----Added NEW_VAR----");
    printf("environ:  %p\n", environ);
    printf("envp:     %p\n", envp);

    exit(EXIT_SUCCESS);
}

輸出:

environ:  0x7fffa05a7fe8
envp:     0x7fffa05a7fe8
----Added NEW_VAR----
environ:  0x5646431276b0
envp:     0x7fffa05a7fe8

使用 envp 變數在 C 語言中遍歷定義的環境變數

前面的程式碼例子說明了為什麼應該避免在呼叫 setenv 函式後使用 main 函式引數 envp 檢索環境變數。當呼叫 setenv 函式時,環境被重新定位,但 envp 仍然指向舊環境。下面的示例程式碼通過用 setenv 呼叫定義一個新的變數,然後遍歷 envp 指標陣列來演示錯誤的行為。請注意,如果找到名為 NEW_VAR 的變數,我們還利用 goto 語句跳轉到迴圈的末端。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[], const char *envp[]) {

    if (setenv("NEW_VAR", "new_value", 1) != 0) {
        perror("setenv");
        exit(EXIT_FAILURE);
    }

    if (envp != NULL) {
        for (size_t i = 0; envp[i] != NULL; ++i) {
            if (strcmp(envp[i], "NEW_VAR=new_value") == 0) {
                puts(envp[i]);
                goto END;
            }
        }
        printf("No such variable found!\n");
    } END:

    exit(EXIT_SUCCESS);
}

輸出:

No such variable found!

使用 environ 變數在 C 語言中遍歷定義的環境變數

由於前面的解決方案找不到新定義的變數,我們應該使用外部宣告的 environ 變數。在這種情況下,我們包含了多個前處理器條件語句,以使程式碼在不同的系統中可移植,但在大多數基於 UNIX 的系統中只需要 extern char **environ。一旦宣告,我們就可以使用我們在上一個例子中實現的相同的迴圈來遍歷變數列表。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if defined (_POSIX_) || defined (__USE_POSIX)
extern char **environ;
#elif defined(_WIN32)
_CRTIMP extern char **_environ;
#endif

int main(void) {

    if (setenv("NEW_VAR", "new_value", 1) != 0) {
        perror("setenv");
        exit(EXIT_FAILURE);
    }

    if (environ != NULL) {
        for (size_t i = 0; environ[i] != NULL; ++i) {
            if (strcmp(environ[i], "NEW_VAR=new_value") == 0) {
                puts(environ[i]);
                goto END;
            }
        }
        printf("No such variable found!\n");
    } END:

    exit(EXIT_SUCCESS);
}

輸出:

NEW_VAR=new_value
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn