2014-01-11 3 views
1

Я читал, что * (умножение) имеет более высокую предрасположенность, чем / (деление). Таким образом, если есть уравнение с * и /, то сначала должно состояться *.Умножение и деление: странный вывод в c

Но я видел программу, вывести что-то странное

#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); 
    printf("Result = %f", a); 
    return 0; 
} 

При выполнении этого, я думал, что выход будет -25, но на самом деле это было -100.

Когда я искал объяснение это было

Step 2: a = 2*(s-u*t)/SQUARE(t); becomes, 

// Here SQUARE(t) is replaced by macro to t*t 
=> a = 2 * (10 - 30 * 2)/t * t; 

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

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

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

/*till here it's OK*/ 
/*why it divided -50 by 2 before multiplying 2*2 and -50*2 */ 
=> a = 2 * (-25) * 2 ; 

=> a = (-50) * 2 ; 

=> a = -100; 

Может ли один объяснить, пожалуйста?

+0

Еще одна ссылка: http://msdn.microsoft.com/en-us/library/126fe14k.aspx – Inisheer

+0

У этого есть много дубликатов, например.g [Странное поведение макрорасширения] (http://stackoverflow.com/questions/15337185/strange-behavior-of-macro-expansion) –

ответ

6

Paranchesis paranoia! Ваш макрос должен быть:

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

Другие правила приоритета и расширение макросов будут делать странные вещи. Ваш макрос:

100/SQUARE(2) 

будет расширяться:

100/2*2 

и читается как:

(100/2) * 2 

, который 100, а не 25.

Другая аномалия, а не в ваш код, если вы попытаетесь выразить квадрат выражения:

SQUARE(2+2) 

расширится

2+2*2+2 

, который 8, не ожидается 16.

Заключение: в макросах написано много круглых скобок. Везде.

+0

Не везде, только вокруг макропараметров (и где они, естественно, должны быть). ;-) –

+0

@ tristopia: Да, и вокруг всего выражения. Я преувеличивал эффект. – rodrigo

+0

Я получил его сейчас большое спасибо – Salahuddin

2

Она не делает то, что вы думаете, он делает: после того, как шаг отмечен /*till here it's OK*/, операции протекают в их обычном порядке для мультипликативных операторов, то есть слева направо:

=> a = 2 * (-50)/2 * 2 ; 
/*till here it's OK*/ 
=> a = -100/2 * 2 ; // Division 
=> a = -50 * 2 ;  // Multiplication 
=> a = -100 ;   // Done 

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

#define SQUARE(X) ((x)*(x)) 
// Still not good: 

int a = 2; 
// Undefined behavior, because ((a++)*(a++)) uses expressions with side effects without a sequence point 
int b = SQUARE(a++); 

По этой причине, вы бы лучше сделать SQUARE функции.

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