2010-09-15 9 views
9

Właśnie przechodziłem przez pewien kod, który często jest zadawany w wywiadach. Wpadłem na pewne pytania, czy ktoś może mi w tym pomóc?Kwadrat liczby definiowanej przy użyciu #define

Jestem całkowicie zdezorientowany na to teraz,

#include <stdio.h> 
#include <conio.h> 

#define square(x) x*x 

main() 
{ 
     int i, j; 
     i = 4/square(4); 
     j = 64/square(4); 
     printf("\n %d", i); 
     printf("\n %d", j); 
     printf("\n %d", square(4)); 
     getch(); 
} 

Wyjście jest:

4 
64 
16 

Zastanawiam się, dlaczego square(4) Zwraca 1, gdy dzieli ją? Chodzi mi o to, jak mogę uzyskać wartość 4 i 64 kiedy ją dzielę, ale kiedy jestem bezpośrednio wykorzystany otrzymuję !!?

+1

Należy zauważyć, że #define kwadrat (x) x * x jest klasycznym C baddy. Spróbuj pętli z kwadratem (x ++); – Jaydee

+5

Jeśli naprawdę chcesz się pomylić i nie przeczytałeś jeszcze żadnej z odpowiedzi, spróbuj zastąpić 'square (4)' wszędzie za pomocą 'square (3 + 1)'. – JeremyP

+0

To był prosty problem z priorytetem. –

Odpowiedz

26

square jest niedostatecznie nawiasach: rozwija wzbudzający, tak

#define square(x) x*x 
    ... 
i=4/square(4); 

oznacza

i=4/4*4; 

które grupy jak (4/4) * 4.Aby ustalić, dodać nawiasy:

#define square(x) ((x)*(x)) 

wciąż bardzo niepewna #define jak ocenia x dwa razy, więc square(somefun()) wywołuje funkcję dwukrotnie i robi nie zatem koniecznie obliczyć kwadrat ale raczej iloczyn dwóch kolejnych połączeń, oczywiście;-).

+0

yea .. rozumiem ... szalał nad nim .. –

+3

+1 dla 'square (somefun())'. Zwykła obserwacja w tym przypadku dotyczy dwukrotnego efektu ubocznego, ale jeśli wyobrazisz sobie 'square (rand())' otrzymujesz iloczyn dwóch liczb losowych, a nie kwadratu pojedynczej liczby losowej. – RBerteig

2

Pierwszeństwo operatora cię rani.

Makro jest rozwijany przez preprocesor taki że

i=4/4*4; 
    j=64/4*4; 

co jest równoważne:

i=(4/4)*4; 
    j=(64/4)*4; 
1

j = 4/square(4) == 4/4*4 == 1*4 == 4

4

Kiedy piszesz i=4/square(4), preprocesor, że rozszerza się i = 4/4 * 4 .
Ponieważ C grupuje operacje od lewej do prawej, kompilator interpretuje to jako i = (4/4) * 4, co jest równoważne 1 * 4.

Trzeba dodać nawiasy, tak:

#define square(x) ((x)*(x)) 

ten sposób i=4/square(4) zamienia i = 4/((4) * (4)).
Potrzebne są dodatkowe nawiasy wokół x w przypadku pisania square(1 + 1), które w innym przypadku zmieni się w 1 + 1 * 1 + 1, które jest oceniane jako 1 + (1 * 1) + 1 lub 3.

3
i=4/square(4); 

rozszerza się

i=4/4*4; 

którego odpowiednikiem

i=(4/4)*4; 
0

Ręcznie poszerzyć makra w kodzie, i będzie jasne. To znaczy, zamień cały kwadrat (x) na dokładnie x * x, w szczególności nie dodawaj żadnych nawiasów.

0

określić tylko tekst makro

main() 
{ 
     int i,j; 
     i=4/ 4 * 4; // 1 * 4 
     j=64/4 * 4; // 16 * 4 
     printf("\n %d",i); 
     printf("\n %d",j); 
     printf("\n %d",square(4)); 
     getch(); 
} 
0

To makro! Więc zwraca dokładnie co zastępuje.

i = 4/4*4; Which is 4... 
j = 64/4*4; Which is 16... 

Wypróbuj za makro:

#define square(x) ((x)*(x)) 
0

Ponieważ pierwszeństwa operatora w wyrażeniu po preprocesora - trzeba pisać

#define square(x) (x*x) 
0

jak inne odpowiedzi powiedzieć, jesteś nagrywany przez pierwszeństwo operatora. Zmień kwadratowe makro na:

#define square(x) (x*x) 

i będzie działać tak, jak oczekujesz.

2

To dlatego, że kompilator zastępuje go:

i=4/4*4; 
j=64/4*4; 

i = (4/4) * 4 = 1 * 4 = 4.

j = (64/4) * 4 = 16 * 4 = 64.