#новичкам
Переменные окружения - это пары "ключ-значение", которые хранятся в операционной системе и доступны всем процессам. Они часто используются для:
- Конфигурации приложений
- Хранения чувствительных данных (паролей, ключей API)
- Управления поведением программ
Самый банальный пример - PATH. В этой переменной окружения находится список путей для поиска исполняемых файлов системой. Добавив путь к своей утилите в эту переменную, вы сможете ее запускать без указания полного пути.
Или например, более приближеный к плюсам пример, LD_LIBRARY_PATH. Это список путей, в котором линкер ищет указанные при линковке библиотеки.
И мы можем прочитать из плюсового кода переменные окружения с помощью С++11 функции std::getenv:
#include <cstdlib>
char* std::getenv(const char* name);
Это скоммунизженная из Сей функция, которая принимает имя переменной окружения и возвращает ее содержимое. Если искомой переменной не существует, возвращается nullptr.
Почему-то они решили возвращать неконстантный указатель, поэтому если уже в вашу голову пришла мысль как-то поменять данные по этому указателю, то не стоит этого делать. Получите UB.
При запуске программы ОС копирует переменные окружения, видимые родительскому процессу, внутрь программы и таким образом они окружение программы перестает зависеть от внешнего мира.
Допустим, пишите вы какой-нибудь свой клиент-сервер на Boost.Asio. Хочется конфигурировать клиента адресом и портом сервера извне, чтобы иметь возможность по-разному запускать клиента локально и, допустим, через docker-compose. Конфиг и его парсилку писать довольно муторно, а адекватную парсилку аргументов командной строки - еще сложнее. Даже если использовать готовые решения в виде json парсера и boost.program_options.
Вместо этих решений можно передавать креды подключения к серверу через переменную окружения:
#include <boost/asio.hpp>
#include <iostream>
#include <cstdlib>
using boost::asio::ip::tcp;
int main() {
try {
// HERE
const char* host = std::getenv("SERVER_HOST");
const char* port = std::getenv("SERVER_PORT");
if (!host || !port) {
std::cerr << "Please set SERVER_HOST and SERVER_PORT environment variables\n";
return 1;
}
boost::asio::io_context io_context;
// Создаем и соединяем сокет
tcp::socket socket(io_context);
tcp::resolver resolver(io_context);
boost::asio::connect(socket, resolver.resolve(host, port));
// Отправляем тестовое сообщение
std::string message = "Hello from Boost.Asio client!\n";
boost::asio::write(socket, boost::asio::buffer(message));
// Читаем ответ (до символа новой строки)
boost::asio::streambuf response;
boost::asio::read_until(socket, response, '\n');
// Выводим ответ
std::istream is(&response);
std::string reply;
std::getline(is, reply);
std::cout << "Server replied: " << reply << std::endl;
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
return 1;
}
return 0;
}
Всего две строчки и никакой мороки! Очень удобная и полезная функция.
Explore your enviroment. Stay cool.
#cpp11