- Overview
-
Table of Contents
- Special Member Functions: Constructors, Destructors, and the Assignment Operator
- Operator Overloading
- Memory Management
- Templates
- Namespaces
- Time and Date Library
- Streams
- Object-Oriented Programming and Design Principles
- The Standard Template Library (STL) and Generic Programming
- Exception Handling
- Runtime Type Information (RTTI)
- Signal Processing
- Creating Persistent Objects
- Bit Fields
- New Cast Operators
- Environment Variables
- Variadic Functions
- Pointers to Functions
- Function Objects
- Pointers to Members
- Lock Files
- Design Patterns
- Dynamic Linking
- Tips and Techniques
- Five Things You Need to Know About C++11 Unions
- A Tour of C99
- A Tour of C1X
- C++0X: The New Face of Standard C++
- C++0x Concurrency
- The Reflecting Circle
- We Have Mail
- The Soapbox
- Numeric Types and Arithmetic
- Careers
- Locales and Internationalization
Environment Variables
Last updated Jan 1, 2003.
Environment Variables
An environment variable consists of a pair of strings: the variable itself, followed by = and its associated value. For example:
PATH=C:\WINDOWS
Environment variables pass information to and from a process. One benefit of this capability is that they enable you to reconfigure a process while it's running, without interrupting the execution of that process.
For example, instead of hard-coding an IP address inside the program's source code, you can store the address in an environment variable that the process accesses at runtime. To change that IP address, you don't have to change the program. The next time your application reads the environment variable, it will obtain the new IP address.
There are two types of environment variables. The first are those confined to a single process. More powerful environment variables are globally accessible to multiple processes or to the entire system. Because each operating system defines its own security restrictions regarding the privileges required for reading and changing environment variables, so I will not discuss these issues here.
Defining Environment Variables from the Command Line
In DOS and Windows, you can define an environment variable from the command line or from a batch file, using the SET command followed by an assignment expression. The following line creates an environment variable called VERSION whose value is 1.1.3:
SET VERSION=1.1.3
In POSIX systems, you omit the SET command:
VERSION=1.1.3
Reading an Environment Variable Programmatically
A program's environment is made available to it at startup. The environment consists of an array of C-strings, each in the form: "VAR=value". You access environment variables from a program using the functions getenv() and putenv(). The ANSI C function getenv() provides an easy and portable way for readimg an environment variable. getenv() is declared in <cstdlib> and has the following prototype:
char * getenv(const char * name);
On success, it returns a pointer to a null-terminated char array that contains the variable's value. If the variable is not defined, getenv() returns NULL. For example
#include <cstdlib.>
#include <iostream>
using namespace std;
int main()
{
char * descr = getenv("PATH");
if (descr)
cout<<"value of PATH is: "<< descr<<endl;
else
cout<<"variable not defined"<<endl;
}
Another quasi-standard manner of accessing a process's environment is mostly used in POSIX systems. To access environment variables in this manner, you use a special form of main() that automatically reads the process's environment at startup and stores it in the argument envp:
int main(int argc, char * argv[], char *envp[])
At startup, the variable envp Is set to point to the process's environment, which is in the form of an array of C-strings. Thus, you may access the first environment variable like this:
const char *var= envp[0] if (var) cout<<"first environment variable is: "<<var<<endl;
The last element in the array is a NULL pointer indicating the end of the array. This enables you traverse the entire array easily:
//execute loop so long as nevp[n] isn't NULL for (int n=0; envp[n]; n++) cout << envp[n]<<endl;
Note that under most POSIX systems you can access the process's environment by using the global variable environ, which is defined in <unsitd.h>. (Note that this isn't a standard header file and as such it might not available on all platforms). For example, the previous code sample can be rewritten like this:
#include <unistd.h>
int main()
{
//execute loop so long as environ[n] isn't NULL
for (int n=0; environ[n]; n++)
cout << environ[n]<<endl;
}
However, using the third main() argument envp makes your intent more explicit, saves you the trouble of locating the definition of environ, and is more portable.
Setting an Environment Variable
To define an environment variable or change the value of an existing variable, use the putenv() function. putenv() isn't defined by the ANSI/ISO standard. In practice, however, both POSIX and Windows implementations declare it in <cstdlib> as a non-standard extension, so it's a relatively portable. putenv() has the following prototype:
int putenv(const char * var);
The argument var must be a string in the form "VAR=VAL". putenv() adds the variable VAR to the current environment and assigns the value VAL to it. If the variable already exists, putenv() overrides the existing value. If you prefer not to override a variable's value, check whether it already exists by calling getenv() before calling putenv(). The following example adds a new environment variable called TEMP whose value is C:\TEMP (remember that a backslash must appear as a \\ inside a quoted literal string in C/C++). On success, putenv() returns 0, and -1 otherwise.
int stat = putenv("TEMP=C:\\TEMP");
if (!stat)
{
cout<<"failed to define environment variable"<<endl;
}
Dealing with wchar_t Strings
Certain implementations also defines wchar_t versions of getenv() and putenv():
wchar_t * _wgetenv(const wchar_t * name); int _wputenv(const wchar_t * var);
You may use these versions when you need to manipulate wchar_t environment variables.
Uses of Environment Variables
As previously said, environment variables enable you to control the program's behavior without having to make changes to its source files or recompiling it. For instance, you can control whether a program displays debug information on the screen simply by defining an appropriate environment variable.
This is particularly useful if you need to enable debugging output at a customer's site without having to reinstall anything. In the following example, the program displays debug information only if the environment variable DBG is defined:
void func();
#include <stdlib.h>
#include <stdio.h>
int main()
{
bool debug=false;
if (getenv("DBG"))
debug=true;
if (debug)
cout<<"calling func"<<endl;
func();
if (debug)
cout<<"returned from func"<<endl;
}
Summary
Environment variables are a simple -- albeit limited -- means of passing information to and from a process without resorting to complex inter-process communication APIs or worse yet, recompiling code. The getenv() and putenv() functions enable you to retrieve and set an environment variable. In addition, certain implementations allow you to access a process's environment through a special argument of main() or via a global variable. Each systems sets limits on the length of an environment variable and the total number of environment variables. In addition, there are security restrictions regarding users' authorizations to read, define and override environment variables.


