Запятая в условном выражении - PullRequest
5 голосов
/ 24 января 2011

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

Я понимаю, что в присваиваниях он оценивает первый операнд, отбрасывает результат, затем оценивает второй операнд.

Но для этого кода, что он должен делать?

CPartFile* partfile = (CPartFile*)lParam;
ASSERT( partfile != NULL );
bool bDeleted = false;
if (partfile,bDeleted)
    partfile->PerformFileCompleteEnd(wParam);

Partfile в IF был ненужным аргументом, или он имеет какое-либо значение?

Ответы [ 5 ]

9 голосов
/ 24 января 2011

В этом случае это ненужное выражение, и его можно удалить, не меняя смысла кода.

4 голосов
/ 24 января 2011

Оператор запятой выполняет выражение первого элемента, отбрасывает результаты, а затем оценивает результат как последнее выражение.

Таким образом, partfile,bDeleted будет вычислять все, что partfile отменит этот результат, затемоценить и вернуть bDeleted

Это полезно, если вам нужно оценить что-то, что имеет побочный эффект (например, вызов метода).В этом случае, однако, это бесполезно.

Для получения дополнительной информации см. Википедия: оператор запятой

2 голосов
/ 24 января 2011
bool bDeleted = false;
if (partfile,bDeleted)
    partfile->PerformFileCompleteEnd(wParam);

Здесь оператор if оценивает partfile, bDeleted, но bDelete всегда ложно, поэтому выражение не запускается. Ключевой вопрос «что это такое?». Вероятный ответ: кто-то временно хотел помешать выполнению оператора partfile->PerformFileCompleteEnd(wParam);, возможно, потому, что он вызывал какую-то проблему, или он хотел, чтобы более поздний код сообщал об ошибках правильно, если этот шаг не был выполнен. Чтобы они помнили, каким был код, они оставили там старую логику «if (partfile)», но добавили жестко закодированную переменную bDeleted, чтобы документировать, что логика partfile->Perform... была фактически «удалена» из программы.

Возможно, лучший способ временно отключить такой код ...

#if 0
    if (partfile)
        partfile->PerformFileCompleteEnd(wParam);
#endif

... хотя иногда я тоже пытаюсь документировать обоснование ...

#ifndef DONT_BYPASS_FILE_COMPLETE_PROCESSING_DURING_DEBUGGING
    if (partfile)
        partfile->PerformFileCompleteEnd(wParam);
#endif

... или ...

if (partFile, !"FIXME remove this after debugging")
    partfile->PerformFileCompleteEnd(wParam);

Лучший выбор зависит от вашего набора инструментов и существующих привычек (например, некоторые редакторы выделяют «FIXME» и «TODO» в обратном видео, поэтому трудно пропустить или заштриховать блоки #if 0; у вас могут быть определенные строки вашего источника - контрольная проверка предупреждает о том, что препроцессор определяет только в отладочных или выпускных сборках, может предотвратить случайное распространение и т. д.).

1 голос
/ 24 января 2011

Оператор запятой является довольно неясной особенностью C / C ++. Его не следует путать с запятой в инициализирующих списках (то есть: int x, int y;) или с запятой разделения параметров вызова функции (то есть: func (x, y)).

Оператор запятой имеет одну единственную цель: дать программисту гарантированный порядок вычисления выражения. Почти для каждого оператора в C / C ++ порядок вычисления выражений не определен. Если я напишу

результат = х + у;

, где x и y являются подвыражениями, тогда сначала могут быть вычислены x или y. Я не могу знать, что, это до компилятора. Однако если вы напишите

результат = x, y;

Порядок оценки гарантируется стандартом: сначала слева.

Конечно, использование этого в реальных приложениях весьма ограничено ...

1 голос
/ 24 января 2011

partfile оценивается, затем bDeleted оценивается и используется в качестве теста. Поскольку оценка partfile не имеет побочных эффектов, удаление его из условного не имеет никакого эффекта.

...