GCC msg "note: in definition of macro 'max'" сообщение об ошибке

Я использую плату серии ATtiny x5 для компиляции своего проекта (файл .cpp.ino). Всякий раз, когда я использую макрос max(a,b), я получаю следующее сообщение:

"C:\Documents and Settings\<user>\Local Settings\Application Data\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.3-arduino2/bin/avr-g++" -c -g -Os  -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=attiny85 -DF_CPU=8000000L -DARDUINO=10609 -DARDUINO_AVR_ATTINYX5 -DARDUINO_ARCH_AVR   "-IC:\Documents and Settings\<user>\Local Settings\Application Data\Arduino15\packages\ATTinyCore\hardware\avr\1.1.1\cores\tiny" "-IC:\Documents and Settings\<user>\Local Settings\Application Data\Arduino15\packages\ATTinyCore\hardware\avr\1.1.1\variants\tinyX5" "-IC:\Documents and Settings\<user>\My Documents\Arduino\libraries\Pins_xxxxx" "-IC:\Documents and Settings\<user>\My Documents\Arduino\libraries\TinyWireS" "C:\WINDOWS\TEMP\build18f8c74edd63168be814edc24cb0a11a.tmp\sketch\AT85PWM.ino.cpp" -o "C:\WINDOWS\TEMP\build18f8c74edd63168be814edc24cb0a11a.tmp\sketch\AT85PWM.ino.cpp.o"
C:\Documents and Settings\<user>\Local Settings\Application Data\Arduino15\packages\ATTinyCore\hardware\avr\1.1.1\cores\tiny/Arduino.h:54:24: note: in definition of macro 'max'
 #define max(a,b) ((a)>(b)?(a):(b))
                        ^

Что означает примечание: в определении макроса 'max', нужно ли мне что-то с этим делать, и если да, то что?

Поиск сообщения в Google дает множество выходных списков компилятора с сообщением, но публикация всегда связана с другим другим сообщением, которое вызывает проблемы. Ни одно из исправлений из этих сообщений не касается сообщения max note:.

, 👍0

Обсуждение

Это единственное сообщение? Не могли бы вы опубликовать свой код или хотя бы [минимальный, полный и проверяемый пример] (http://stackoverflow.com/help/mcve). Я подозреваю, что это как-то связано с типами данных, которые используются, когда вы используете max в каком-то контексте., @Nick Gammon

Я потратил добрый час, пытаясь упаковать что-нибудь небольшое для вас, прежде чем я решил прервать., @HiTechHiTouch

@Ник, я потратил добрый час, пытаясь собрать для тебя что-нибудь маленькое, прежде чем решил прервать. Основная проблема заключалась в вызове функции, где MAX использовался для вычисления одного параметра, а макрос использовался для попытки извлечения поля из структуры для использования в качестве другого параметра. Из-за того, что C++ настаивает на том, что структуры являются классами, и, следовательно, выполняется поиск процедуры явного преобразования, макрос, используемый для извлечения поля, помечается вместе со всеми другими макросами при вызове функции. Это кажется чересчур усердным, но лучше иметь слишком много информации..., @HiTechHiTouch

И есть правило 5 минут на редактирование комментариев. Должно быть около 30. Некоторые из нас медленно соображают, им нужно свериться со ссылками, нужно время, чтобы отредактировать.... Бззззззззз, ваше время истекло, следующий участник, пожалуйста!, @HiTechHiTouch

Недавно я работал над другим проектом, где получил похожее сообщение. Однако *раньше* это было настоящее сообщение об ошибке/предупреждение. Строка «примечание» просто сообщает вам, где определен макрос. «Настоящая» ошибка/предупреждение возникает, когда макрос *используется* (потому что именно здесь у вас могут быть, например, несоответствия со знаком/без знака)., @Nick Gammon


2 ответа


1

Примечание на будущее:

(Моим конкретным случаем был вызов функции с несколькими параметрами. У одного был max(a,b), а у другого параметра была ошибка. Он использовал другой макрос, который мог компилятор помечает каждый макрос во всем вызове).

Сообщение выглядит отвлекающим маневром, поскольку с определением макроса max(a,b) проблем нет. Я подозреваю, что он помечен только потому, что он косвенно связан с оператором с ошибкой.

Поскольку это не было частью проблемы, компилятор не мог сказать ничего конкретного ни об этом, ни о сгенерированном коде. Поэтому сообщение с пометкой заканчивается тем, что говорит «в определении макроса» (своего рода крайняя мера по умолчанию), поскольку ничего более конкретного сказать не может.

Если вы когда-нибудь получите одну из них, особенно из системного макроса, игнорируйте ее, пока не диагностируете другие проблемы.

Игнорируйте тот факт, что сообщение об ошибке стоит первым в списке, а инструкция, использующая макрос, не будет помечена, пока не будет помечено несколько других инструкций.

Опять же, я подозреваю, что компилятор чувствует себя обязанным что-то сказать о макросе, потому что он был использован. Но поскольку это не является частью проблемы в утверждении, где оно появляется, оно не помечается там. Вместо этого компилятор помещает сообщение вверху, потому что оно должно куда-то идти, но компилятор не может/не хочет ассоциировать его с оператором, в котором оно использовалось.

Это решение сработало для меня, но языковой юрист или разработчик компилятора может сказать, что мое объяснение не имеет под собой никаких оснований.

,

2

Я могу достаточно легко воспроизвести ваше сообщение:

#define max(a,b) ((a)>(b)?(a):(b))

void setup() {
 int b = 66;
 unsigned int c = 42;
 analogWrite (3, max (b, c));
}

void loop() { }

Я получаю следующие предупреждения:

/tmp/arduino_modified_sketch_857720/sketch_aug31a.ino: In function 'void setup()':
/tmp/arduino_modified_sketch_857720/sketch_aug31a.ino:1:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define max(a,b) ((a)>(b)?(a):(b))
                         ^
/tmp/arduino_modified_sketch_857720/sketch_aug31a.ino:6:18: note: in expansion of macro 'max'
  analogWrite (3, max (b, c));

Дело в том, что предупреждение примечание: в расширении макроса 'max' просто говорит вам, где макрос определен, поэтому вы можете понять настоящее предупреждение. настоящее предупреждение: предупреждение: сравнение целочисленных выражений со знаком и без знака

Итак, читая их вместе, вы сравниваете (в макросе) число со знаком и без знака, и компилятор предупреждает вас об этом.

Сообщение выглядит отвлекающим маневром, учитывая, что с определением макроса max(a,b) проблем нет. Я подозреваю, что он помечен только потому, что он косвенно связан с оператором с ошибкой.

Верно. В этом макросе проблем нет. Макросы могут генерировать странные сообщения об ошибках, потому что они просто заменяют текст. Например:

max (the quick brown fox, jumps over the lazy dog);

Это вызовет множество ошибок, в том числе "примечание" к месту определения max. В max нет ничего плохого, пока вы не попытаетесь наполнить его мусором.


Шаблоны

Это одна из причин, по которой я предпочитаю по возможности избегать макросов. Вы можете сделать «максимум» с помощью шаблона. Например:

#undef max   // удалить исходный макрос в заголовочном файле Arduino

template<typename T> T max (T a, T b)
  {
  if (a > b)
    return a;

  return b;
  }

Теперь вы получаете немного более разумные сообщения об ошибках:

/tmp/arduino_modified_sketch_711186/sketch_aug31a.ino: In function 'void setup()':
sketch_aug31a:14: error: no matching function for call to 'max(int&, unsigned int&)'
   analogWrite (3, max (b, c));
                            ^
/tmp/arduino_modified_sketch_711186/sketch_aug31a.ino:14:28: note: candidate is:
/tmp/arduino_modified_sketch_711186/sketch_aug31a.ino:3:24: note: template<class T> T max(T, T)
 template<typename T> T max (T a, T b)
                        ^
/tmp/arduino_modified_sketch_711186/sketch_aug31a.ino:3:24: note:   template argument deduction/substitution failed:
/tmp/arduino_modified_sketch_711186/sketch_aug31a.ino:14:28: note:   deduced conflicting types for parameter 'T' ('int' and 'unsigned int')
   analogWrite (3, max (b, c));
                            ^
exit status 1
no matching function for call to 'max(int&, unsigned int&)'

Конечно, теперь вы перешли от предупреждения к ошибке, потому что шаблону нужен один тип.

Обратили внимание на примечания? Это просто компилятор пытается быть полезным.


Вы можете сделать так, чтобы шаблон принимал два типа, если вы готовы угадать тип возвращаемого значения (это будет первый тип или второй тип?):

#undef max

template<typename T1, typename T2> T1 max (T1 a, T2 b)
  {
  if (a > b)
    return a;

  return b;
  }

Теперь вы не получите сообщение об ошибке или предупреждение, однако результатом будет первый тип (T1), который может вам подойти или не подойти.

,

Это не так. Вы построили пример, в котором операнды макроса max() были ошибочными. В моем случае операнды макроса max() были в порядке, и соответствующая диагностика включала другой макрос. max() не был частью ошибочного выражения., @HiTechHiTouch

Что касается шаблонов: макрос max() поставляется с базой Arduino IDE. Возможно, вы были бы в лучшем положении, чем я, чтобы заставить IDE перейти на шаблоны., @HiTechHiTouch

вы были бы в лучшем положении, чем я, чтобы заставить IDE переключиться на шаблоны - Если бы они это сделали, это, вероятно, выдало бы кучу предупреждений или даже ошибок в коде, который в настоящее время компилируется только с предупреждением. . Так что, наверное, не будут. max() не был частью выражения по ошибке - да, я хотел бы увидеть это воспроизведенным, прежде чем я смогу согласиться., @Nick Gammon

«соответствующая диагностика включала другой макрос» — было бы полезно опубликовать все диагностики, а не только те, которые связаны с «max». Плюс определения для этого другого макроса и строки кода, вызвавшие ошибку., @Nick Gammon