我编写了一些小的方便函数,通过包装std::getenv
、setenv
和environ
来处理C++中的环境变量。除了设置和获取环境变量外,我还提供了检查当前环境是否包含某个变量的功能。
#include <cstdlib>
#include <unistd.h>
template <typename VAR_TYPE>
void set(const std::string& variableName, VAR_TYPE varValue, bool overwrite = false) {
if (!setenv(variableName.c_str(), std::string(variableValue).c_str(), overwrite)) {
if (errno == ENOMEM) {
throw std::bad_alloc();
} else if (errno == EINVAL) {
throw std::invalid_argument("Variable name invalid: " + variableName);
} else {
throw std::runtime_error("Failed to set environment variable " + variableName);
}
}
}
std::string load(const std::string& variableName, const std::string& defaultValue = "") {
if (const char* envVariable = std::getenv(variableName)) {
return std::string(envVariable);
}
return defaultValue;
}
bool contains(const std::string& variableName) {
for (char** currentEnviron = environ; *currentEnviron; currentEnviron++) {
if (!std::strncmp(variableName.c_str(), *currentEnviron, variableName.length())) {
return true;
}
}
return false;
}
但是,根据定义,这只允许访问NAME=VALUE
形式的环境变量。
在bash
中,我可以执行以下操作:
$> export SOME_VAR
$> export -p | grep SOME_VAR
declare -x SOME_VAR
显然,SOME_VAR
是在某个地方定义的,即使我没有给它赋值。然而,当我运行printenv
时,它使用了我在包装中使用的相同方法,SOME_VAR
没有列出。我看过/proc/self/environ
,但它只列出了具有赋值的变量。
我的问题是:
- 定义为
SOME_VAR_WITH_VALUE=42
和SOME_VAR_WITHOUT_VALUE
的环境变量之间有什么区别 - 在C/C++中是否有可能访问没有值的环境变量
Shell有内部和导出环境变量的概念。
像ABC=xyz
这样的shell命令设置一个内部变量(可以在使用set
的Bash中看到(。
要导出内部变量,可以使用export
命令。
export ABC=xyz
将创建一个内部变量并导出它(使用env
可以看到导出的变量(。
export ABC
本身不定义任何变量,它只是标记要导出的ABC
,定义时。
举个例子:
$ ABC=xyz
$ set | grep ABC
ABC=xyz
$ env | grep ABC
现在有了export
:
$ export ABC
$ set | grep ABC
$ env | grep ABC
$ ABC=xyz
$ set | grep ABC
ABC=xyz
$ env | grep ABC
ABC=xyz
请注意变量在设置时是如何导出的。所以export ABC
纯粹是一个shell特性,它不会修改环境。没有API。
要设置具有空值的环境变量,请使用export ABC=""
:
$ export ABC=""
$ env | grep ABC
ABC=
首先尝试这个:
export SOME_VAR
set | grep SOME_VAR
第二行将不返回任何内容。这是因为第一行没有定义SOME_VAR
。
至于你的两个问题:
- CCD_ 23无明显作用。它不会创建没有值的变量,也不会更改已设置变量的值
- 环境变量总是有一个值,但该值可能是空字符串。如果您尝试访问不存在的变量,您将得到
NULL
最终,bash
只是另一个Linux程序。所涉及的魔法是有限的。它可以更改libc
environ
变量,但也可以有自己的内部变量。如果在/proc/sef/environ
中看不到SOME_VAR_WITHOUT_VALUE
,则可以推断它是某种bash内部变量。
注意,bash
和大多数Linux程序一样,可以并行运行多次。环境在进程之间是分开的。因此,即使在C中,也不能直接访问任何bash环境变量。当您的流程启动时,bash会将其环境复制到您的环境中,这是您在利用这一事实。但env -i your_process
甚至会阻止这种情况。