2015-08-11 2 views
-5
#include<stdio.h> 
#define SQUARE(x) x*x 
int main(){ 
float s=10,u=30,t=2,a; 
a=2*(s-u*t)/SQUARE(t); // How is this evaluated ? 
printf("Result %f\n",a); 
return 0; 
} 

Выходной сигнал, отображаемый компилятором, составляет -100,000000. Но по мне это должно быть -25.000000. Что я должен сделать, чтобы исправить это и что такое моя ошибка?Как будет оцениваться этот препроцессор C?

+2

'# define' делает * буквальную замену строки *. Таким образом, вы получите 'a = 2 * (s-u * t)/t * t', который, учитывая операторный порядок оценки, будет оцениваться как: a = (2 * (s-u * t)/t) * t'. Вы, вероятно, действительно хотите 'a = 2 * (su * t)/(t * t)', поэтому вы должны иметь '#define SQUARE (x) ((x) * (x))' – lurker

+0

FWIW, [см. Это] http://en.cppreference.com/w/c/language/operator_precedence). –

+0

Лучший способ узнать: 'cpp your_file.c' – nouney

ответ

2

Препроцессор - это замена текста. Таким образом, ваше выражение становится:

a=2*(s-u*t)/t*t; 

* и / имеют равную precendence, так 2*(s-u*t) получает делится на t затем умноженной на t.

0
#define SQUARE(x) x*x 
int main(){ 
float s=10,u=30,t=2,a; 
a=2*(s-u*t)/t*t; // SQUARE(t) is defined as t*t so it is 
       // what is placed here instead of SQUARE(t) 

Скорее всего, это не то, что вы хотите с /t*t==1.

РЕШЕНИЕ:

#include<stdio.h> 
#define SQUARE(x) ((x)*(x)) 

затем:

#include<stdio.h> 
#define SQUARE(x) x*x 
int main(){ 
float s=10,u=30,t=2,a; 
a=2*(s-u*t)/((t)*(t)); // again, exactly as in #define SQUARE(t) 
5

#define делает буквальную замену строки символов, которые вы определили. Таким образом, выражение:

a = 2*(s-u*t)/SQUARE(t*t) 

расширится:

a = 2*(s-u*t)/t*t 

Который, данный оператор порядок оценки будет оценивать как:

a = (2*(s-u*t)/t)*t 

Не то, что вы хотите. Вы, наверное, очень хочется a = 2*(s-u*t)/(t*t), так что вы должны иметь:

#define SQUARE(x) (x*x) 

или даже лучше, так как @Jongware указывает, так как x сама может быть выражением:

#define SQUARE(x) ((x)*(x)) 

Таким образом, такие выражения, как, SQUARE(a+b) будет правильно оценивают ((a+b)*(a+b)), а не (a+b*a+b).

Также, как указано в комментариях, вы должны остерегаться результатов макрорежима, когда у вас есть побочные эффекты в ваших аргументах. Например, что делает SQUARE(x++), и каково значение x, когда это будет сделано? В этом случае это дало бы (x++)*(x++), причем значение x было бы приращенным дважды, а результаты могут быть неопределенными (зависит от порядка приращения приращения в этом случае).

+4

Слишком немного безопаснее: '#define SQUARE (x) ((x) * (x))'. Он удалит (только) еще одну возможную ошибку: 'SQUARE (1 + 2)'. – usr2564301

+0

@ Jongware да, хорошо поймать! – lurker

+0

FYI (ну, я думаю, вы знаете, но ради других): это * только * удаляет * одну * дополнительную ловушку. Он не защищает от вопиющего неправильного использования, например, в 'SQUARE (x ++)'. – usr2564301

1

Объяснение:

Функция макросъемки SQUARE(x) x*x вычислить квадрат заданного числа «х».

Шаг 1: поплавок s = 10, u = 30, t = 2, a; Здесь переменная s, u, t, a объявляется как тип с плавающей точкой, а переменная s, u, t инициализируется 10, 30, 2.

Шаг 2: a = 2 * (s-u * t)/SQUARE (t); становится,

=> a = 2 * (10 - 30 * 2)/t * t; Здесь SQUARE (t) заменяется макросом на t * t.

=> a = 2 * (10 - 30 * 2)/2 * 2;

=> a = 2 * (10 - 60)/2 * 2;

=> a = 2 * (-50)/2 * 2;

=> a = 2 * (-25) * 2;

=> a = (-50) * 2;

=> a = -100;

Шаг 3: printf ("Результат =% f", a); Он печатает значение переменной 'a'.

Поэтому выход программы -100

Смежные вопросы