Почему значение макроса равно 0 вместо 1? - PullRequest
2 голосов
/ 02 ноября 2011

здесь base->left равно NULL, а base->right->height равно 0:

((((base->left ? base->left->height : -1)) > ((base->right ? base->right->height : -1))) 
? 
((base->left ? base->left->height : -1) + 1) 
: 
((base->right ? base->right->height : -1) + 1))

IMO результат вышеприведенного выражения должен быть 1,

, нополучается, что 0 когда я его распечатываю.

Кто-нибудь знает причину?

Это ошибка в gcc 4.3.2?

ОБНОВЛЕНИЕ

как получается выражение?

#define MAX_PLUS_1(a, b) (((a) > (b)) ? (a + 1) : (b + 1))
#define BINARY_TREE_HEIGHT(node) (node ? node->height : -1)
#define BINARY_TREE_SYN_HEIGHT(left, right) \
    MAX_PLUS_1(\
        BINARY_TREE_HEIGHT(left),\
        BINARY_TREE_HEIGHT(right)\
    )

это действительно BINARY_TREE_SYN_HEIGHT(base->left, base->right)

И проблема исчезнет, ​​если я заменим MAX_PLUS_1 на функцию:

int MAX_PLUS_1(int a, int b){
    return (((a) > (b)) ? (a + 1) : (b + 1));
}

Ответы [ 3 ]

2 голосов
/ 02 ноября 2011

Ваш код плохо разработан.Тот факт, что он работает как функция, позвольте мне подозревать, что это происходит из-за многократной оценки ваших аргументов макроса.

  • никогда не имеет макросов, которые оценивают свои аргументы дважды.Если у аргумента есть побочные эффекты, вы облажались
  • , всегда ставьте скобки вокруг ваших аргументов макроса.В зависимости от аргументов при вызове, приоритет оператора может дать вам нечто совершенно иное, чем вы думаете,
  • , когда это возможно, просто используйте функцию inline вместо макроса.Это так же эффективно, имеет проверку типов и гарантирует, что аргументы вычисляются только один раз.
  • в вашем конкретном случае вообще нет причин иметь +1 внутри макроса.Выделите это вне вызова макроса или функции.
  • вы, кажется, не контролируете типы, которые используете очень хорошо.вы говорите, что ваше поле height относится к типу без знака, но вы даете нам вызов функции с параметрами int.
  • Edit: обычно uint32_t не очень подходит для применениятип.почему 32 бит почему не 64?Лучший стандартный тип без знака для «размеров», «длины» и тому подобного обычно составляет size_t.Пусть система решит, какой тип она обрабатывает лучше всего.
1 голос
/ 02 ноября 2011

Из дополнительной информации в нашем обсуждении Комментариев ваше поле height не подписано.Это означает, что когда вы пытаетесь сравнить его с -1, вы попадаете в беду - (uint32_t)-1 == 0xFFFF_FFFF = Очень большое число, поэтому «левая» ветвь выбирается над «правой» веткой в ​​некоторый момент, когда вы этого не ожидаетек.

Запись MAX_PLUS_1() как функции решает, или, возможно, скорее скрывает, эту проблему, потому что вы используете int для параметров.Это означает, что сравнение выполняется между значением height и (int)-1, что вы и хотели.

0 голосов
/ 02 ноября 2011

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

Если вы замените их значениями для проверки троичного, он действительно напечатает 1

((((0 ? 1 : -1)) > ((1 ? 0 : -1))) 
?
((0 ? 0 : -1) + 1)
:        
((1 ? 0 : -1) + 1));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...