ISO C定义了一个函数getenv,可以用其取环境量值,但是该标准又称环境的内容是由实现定义的。
- #include <stdlib.h>
char *getenv(const char *name);
返回值:返回指向与name关联的value的指针,若未找到则返回NULL
我们应当使用getenv从环境中取一个指定环境变量的值,而不是直接访问environ。
- #include <stdlib.h>
- int putenv(char *str);
int setenv(const char *name, const char *value, int rewrite);
int unsetenv(const char *name);
这三个函数的操作是:
- putenv取形式为name=value的字符串,将其放到环境表中。如果name已经存在,则先删除其原来的定义。
- setenv将name设置为value。如果在环境中name已经存在,那么(a)若rewrite非0,则首先删除其现有的定义;(b)若rewrite为0,则删除其现有定义(name不设置为新的value,而且也不出错)。
- unsetenv删除name的定义。即使不存在这种定义也不算出错。
环境表(指向实际name = value字符串的指针数组)和环境字符串通常存放在进程存储空间的顶部(栈之上)。删除一个字符串很简单--只要先在环境表中找到该指针,然后将所有后续指针都向环境表首部顺次移动一个位置。但是增加一个字符串或修改一个现有的字符串就困难得多。环境表和环境字符串通常占用的是进程地址空间的顶部,所以它不能再向高地址方向(向上)扩展;同时也不能移动在它之下的各栈帧,所以它也不能向地址地方向(向下)扩展。两者组合使得该空间的长度不能再增加。
(1)如果修改一个现有的name:
(a)如果新value的长度少于或等于现有value的长度,则只要在原字符串所用空间中写入新字符串。
(b)如果新value的长度大于原长度,则必须调用malloc为新字符串分配空间,然后将新字符串复制到该空间中,接着使环境表中针对name的指针指向新分配区。
(2)如果要增加一个新的name,则操作就更加复杂。首先,调用malloc为name = value字符串分配空间,然后将该字符串复制到此空间中,则:
(a)如果这是第一次增加一个新name,则必须调用malloc为新的指针表分配空间。接着,将原来的环境表复制到新分配区,并将指向新name = value字符串的指针存放在该指针表的表尾,然后又将一个空指针存放在其后。最后使environ指向新指针表。
(b)如果这不是第一次增加一个新name,则可知以前已调用malloc在堆中为环境表分配了空间,所以只要调用realloc,以分配比原空间多存放一个指针的空间。然后将指向新name = value字符串的指针存放在该表表尾,后面跟着一个空指针。