`getenv`, `getenv_s` 함수

getenv, getenv_s 함수 (getenv, getenv_s)

환경 변수는 프로그램 밖에서 동작을 조정할 수 있게 해 주는 창구예요. 예를 들어 PATHHOME 같은 값이 필요할 때 getenv로 그 값을 읽어 와요. 그냥 읽기만 하는 함수라 단순해 보이지만, 반환된 문자열을 어떻게 대해야 하는지가 미묘해서 그 부분을 꼭 짚어 볼게요.

출처: cppreference

본문

함수 원형

<stdlib.h>에 정의돼 있어요.

char *getenv( const char *name );                                     // (1)

errno_t getenv_s( size_t *restrict len, char *restrict value,         // (2) (since C11)
                  rsize_t valuesz, const char *restrict name );

설명 (Explanation)

  1. 호스트가 제공하는 환경 목록에서 이름이 name인 환경 변수를 찾아, 그 변수에 연결된 문자열을 가리키는 포인터를 돌려줘요. 환경 변수의 집합과 그것을 바꾸는 방법은 구현 정의예요.

    이 함수는 스레드 안전이 보장되지 않아요. getenv에 대한 다른 호출이나 POSIX의 setenv(), unsetenv(), putenv() 호출이 이전 호출이 돌려준 포인터를 무효화하거나 그 문자열을 수정할 수 있어요.

    getenv가 돌려준 문자열을 수정하면 동작이 정의되지 않아요(undefined behavior).

  2. (1)과 같지만, 환경 변수의 값을 사용자가 준 버퍼 value에 쓰고(value가 널이 아니면), 실제로 쓴 바이트 수를 *len에 저장해요(len이 널이 아니면). 환경 변수가 설정되어 있지 않으면 *len0을 쓰고(len이 널이 아니면) value[0]'\0'을 써요(value가 널이 아니면). 또한 다음 오류들을 실행 시 감지해 현재 설치된 제약 핸들러를 호출해요:

    • name이 널 포인터
    • valueszRSIZE_MAX보다 큼
    • value가 널 포인터인데 valuesz가 0이 아님

    다른 모든 경계 검사 함수와 마찬가지로, getenv_s는 구현이 __STDC_LIB_EXT1__을 정의하고 사용자가 <stdlib.h>를 포함하기 전에 __STDC_WANT_LIB_EXT1__을 정수 상수 1로 정의한 경우에만 사용할 수 있다는 점이 보장돼요.

매개변수 (Parameters)

  • name — 찾으려는 환경 변수의 이름을 나타내는 널 종료 문자열
  • lengetenv_s가 환경 변수의 길이를 저장할 사용자 제공 위치를 가리키는 포인터
  • valuegetenv_s가 환경 변수 내용을 저장할 사용자 제공 문자 배열을 가리키는 포인터
  • valueszgetenv_s가 쓸 수 있는 최대 문자 수(버퍼 크기)

반환값 (Return value)

  1. 환경 변수의 값을 나타내는 문자열, 또는 해당 변수가 없으면 널 포인터.

  2. 환경 변수를 찾았으면 0, 찾지 못했거나 실행 제약 위반이 발생했으면 0이 아닌 값. 오류가 나면 *len0을 써요(len이 널 포인터가 아닌 경우).

주의할 점 (Notes)

POSIX에서는 환경 변수를 전역 변수 environ(<unistd.h>extern char **environ;로 선언)이나 main 함수의 선택적 세 번째 인자 envp로도 접근할 수 있어요.

value가 널 포인터이고 valuesz0getenv_s 호출은 전체 결과를 담는 데 필요한 버퍼 크기를 알아내는 용도로 쓰여요.

예제 (Example)

PATH 환경 변수의 값을 읽어 출력하는 간단한 예시예요.

#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    const char *name = "PATH";
    const char *env_p = getenv(name);
    if (env_p)
        printf("Your %s is %s\n", name, env_p);
}

가능한 출력:

Your PATH is /home/gamer/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/share/games