Странный мод оператора (%) результат при использовании #define - PullRequest
2 голосов
/ 29 июля 2011
int temp1,temp2,temp3;
temp1 = 199;
temp2 = 200;
temp3 = 199%temp2;

CString txt;
txt.Format(_T("temp3 = %d"),temp3);
AfxMessageBox(txt);

Выход составляет 199, как и ожидалось.

#define WIDTH 100
#define BUFFERWIDTH 200
int temp1,temp2,temp3;
temp1 = 199;
temp2 = BUFFERWIDTH;
temp3 = 199%BUFFERWIDTH;

CString txt;
txt.Format(_T("temp3 = %d"),temp3);
AfxMessageBox(txt);

Выход составляет 199, как и ожидалось.

#define WIDTH 100
#define BUFFERWIDTH 2*WIDTH
int temp1,temp2,temp3;
temp1 = 199;
temp2 = BUFFERWIDTH;
temp3 = 199%BUFFERWIDTH;

CString txt;
txt.Format(_T("temp3 = %d"),temp3);
AfxMessageBox(txt);

Выход 100 ...

Просто интересно, что вызывает это:)

Ответы [ 9 ]

8 голосов
/ 29 июля 2011

Прочитайте о приоритет оператора и обратите внимание, что вы говорите 199 % 2 * 100.

.,.

или я должен сказать, (199 % 2) * 100 ...

4 голосов
/ 29 июля 2011

Это классическая проблема с препроцессором.Проблема в том, что когда вы пишете

#define BUFFERWIDTH 2*WIDTH
temp3 = 199%BUFFERWIDTH;

Препроцессор расширяет это до

#define BUFFERWIDTH 2*WIDTH
temp3 = 199 % 2 * WIDTH;

Обратите внимание, что это интерпретируется как

temp3 = (199 % 2) * WIDTH;

вместо намеченного

temp3 = 199 % (2 * WIDTH);

Чтобы исправить это, у вас есть несколько вариантов.Во-первых, вы можете заключить в скобки свое определение BUFFERWIDTH следующим образом:

#define BUFFERWIDTH (2*WIDTH)
temp3 = 199%BUFFERWIDTH;

Теперь это расширится до

temp3 = 199 % (2 * WIDTH);

, как и ожидалось.Однако лучшим вариантом было бы использовать const для определения ваших констант:

const int BUFFERWIDTH = 2 * WIDTH;
temp3 = 199%BUFFERWIDTH;

Теперь это интерпретируется правильно, поскольку константы понимаются компилятором, а не препроцессором.

В целом, я настоятельно призываю вас не использовать #define для определения констант.#define по сути является механизмом поиска и замены в исходном коде, который не имеет семантического или синтаксического понимания того, что он заменяет.Это не очень хорошо работает с приоритетом операторов, поэтому вы легко можете столкнуться с такими ошибками.const, с другой стороны, - это , понятный компилятору для определения константы, и поэтому выражения будут правильно вычисляться, когда в игру вступит приоритет оператора.

Надеюсь, это поможет!

1 голос
/ 29 июля 2011

Одна из самых распространенных ошибок при использовании MACROS - не понимание того, что MACROS являются единицами замены кода. Итак, ваш код:

#define BUFFERWIDTH 2*WIDTH
// ...
temp3 = 199%BUFFERWIDTH;

После предварительной обработки преобразуется в:

temp3 = 199%2*100;

Если вы примените приоритет оператора, вы получите номер, который вы показали.

1 голос
/ 29 июля 2011

В последнем случае

temp3 = 199%BUFFERWIDTH;

становится

temp3 = 199%2*WIDTH

, что составляет

temp3 = 199%2*100

, поэтому

temp3 = (199%2) * 100 

, что означает

temp3 = 100.

Перепишите его:

#define BUFFERWIDTH (2*WIDTH)
0 голосов
/ 29 июля 2011

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

#define BUFFERWIDTH ( 2 * (WIDTH) )

, что позволит адаптировать любые изменения, внесенные вами к WIDTH позже:

#define WITDH (10+12*55)

0 голосов
/ 29 июля 2011

Эта строка:

temp3 = 199%BUFFERWIDTH;

разрешается до

temp3 = 199%2*WIDTH;

это не то, что вы хотите. Заключите 2*WIDTH в скобки, и вы получите желаемый результат:

#define BUFFERWIDTH (2*WIDTH)
0 голосов
/ 29 июля 2011

Вы попали в макрос-ловушку приоритета оператора :

temp3 = 199%BUFFERWIDTH;

Становится:

temp3 = 199%2*WIDTH;

Что становится:

temp3 = 199%2*100;

Поскольку % и * имеют одинаковый приоритет, они оцениваются слева направо, и вы получаете temp3 = 1*100;

0 голосов
/ 29 июля 2011

Препроцессор преобразует это в 199*2%200.

Поскольку * имеет более высокий приоритет, чем %, это анализируется как (199 * 2) % 200.

Это один измного причин, по которым нетривиальные #DEFINE s являются злом.
В этом конкретном случае вы можете исправить это с помощью скобок:

#define BUFFERWIDTH (2*WIDTH)
0 голосов
/ 29 июля 2011

В последнем примере 199%BUFFERWIDTH расширяется до 199 % 2 * 100, что соответствует 100.

...