Я пытаюсь создать (используя С++ 17) простой заголовок отладки, который выполняет только некоторые строки кода, если включен флаг LOGGER_DEBUG_MODE. Вот как определяется мой заголовок (я также пытался использовать { x; } вместо x, но предупреждение сохраняется):
отладка.h
#ifndef _HDEBUG
#define _HDEBUG
static bool LOGGER_DEBUG_MODE = true;
#define R_DEBUG(x) if (LOGGER_DEBUG_MODE == true) x
#endif
Я включил debug.h и в какой-то момент своего кода я вызываю функцию макроса R_DEBUG для вывода некоторых значений:
logger_adc.cpp
double anlg_device_t::eval_formula()
{
double result = -9999;
try
{
result = parser.Eval();
}
catch (mu::Parser::exception_type &e)
{
std::cout << e.GetMsg() << std::endl;
}
R_DEBUG(std::cout << "Eval Result: " << result << std::endl);
return result;
}
Я ожидал, что все будет работать правильно, но когда я запускаю make-файл, я получаю это предупреждение:
inc/debug.h:5:14: предупреждение: «LOGGER_DEBUG_MODE» определен, но не используется [-Wunused-variable] статическое логическое значение LOGGER_DEBUG_MODE = true;
Я думал, что мое определение было перепутано, но после проверки временных файлов, созданных g++, оказалось, что препроцессор сделал все, как я ожидал:
logger_adc.ii
double anlg_device_t::eval_formula()
{
double result = -9999;
try
{
result = parser.Eval();
}
catch (mu::Parser::exception_type &e)
{
std::cout << e.GetMsg() << std::endl;
}
if (LOGGER_DEBUG_MODE == true) std::cout << "Eval Result: " << result << std::endl;
return result;
}
Почему я получаю предупреждающее сообщение, даже если переменная LOGGER_DEBUG_MODE явно используется внутри оператора if? Я напутал что-то очевидное, что я не понимаю? Мои флаги компиляции для объектных файлов (где появляется предупреждение) g++ -Wall -Wextra -O1 -g -std=c++17 -save-temps=obj -Iinc -I/usr/local/include -c
плюс pkg-config --cflags --libs libmodbus
Если нужно, это моя основная функция:
main.cpp
#include "logger_adc.h"
int main()
{
anlg_device_t test (ADC_CHIP_1, 1, 18, 1, 1, true);
test.set_formula("2*x","x", test.get_voltage_ptr());
std::cout << "Test Voltage: " << test.get_voltage() << std::endl << "Test Relative: " << test.get_relative() << std::endl;
std::cout << "Test Formula (2*x): " << test.eval_formula() << std::endl;
return 0;
}
Заранее спасибо!
#define _HDEBUG
Это имя зарезервировано для языковой реализации. Определив его, ваша программа будет иметь неопределенное поведение. Вы должны использовать другое имя для вашего макроса.
@eerorika Поменяла на _HLOGGERDEBUG
, спасибо!
@LucasVaz Это имя также зарезервировано. Вы должны выбрать другой.
@eeorika zzzzzz, изменила на _HDATALOGGERSIGMADEBUG
. Если это зарезервировано, я сдаюсь.
@eerorika Я только что искал, почему вы просто не сказали, что любое имя, начинающееся с подчеркивания, за которым следует заглавная буква, зарезервировано?
@LucasVaz Я хотел, чтобы вы научились самостоятельно изучать языковые правила. Это ценный навык для программиста.
У вас есть заголовок, который определяет static bool LOGGER_DEBUG_MODE =true;
. Если вы включите этот заголовок в несколько файлов C++, каждый файл получит свою собственную копию этого логического значения.
В вашем main.cpp вы не используете R_DEBUG
, поэтому копия этого логического значения (которое предположительно происходит от включения logger_adc.h
) действительно не используется в этом файле.
Возможные решения:
Вы должны сделать так, чтобы у вас была только одна копия этого логического значения (объявите его в заголовке с помощью extern
и определите в одном файле C++.
Используйте определения сборки вместо проверок во время выполнения
и т. д.
Я думал, что статические переменные уже разделены между объектами, это многое объясняет. Так станет что-то вроде extern bool LOGGER_DEBUG_MODE;
в шапке и bool LOGGER_DEBUG_MODE = true;
в основном (например)?
Статический — это перегруженный термин в C++. В классе переменная static
действительно является общей для всех экземпляров этого класса. Как глобальная переменная, static
означает, что она локальна для этого файла C++ (технически единица перевода).
В качестве общего совета, связанного с вашей проблемой: не пытайтесь создавать потоки управления с помощью статических (константных) переменных, если это возможно. Если требуется переключатель времени компиляции (что, похоже, имеет место именно здесь), используйте только схемы времени компиляции, если это возможно (#ifdefs или constexpr, начиная с C++17).