Почему моя программа на 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\n",a);
return 0;
}

По моему мнению, вывод этой программы должен быть -25.000, но я получаю -100.000.

И во второй программе:

#define FUN(i,j) i##j
int main()
{
int val1 = 10;
int val12 = 20;
clrscr();
printf("%d\n",FUN(val1,2));
getch();
}

Вывод должен быть 102, но я получаю 20; почему это так?


person Amit Singh Tomar    schedule 07.03.2011    source источник
comment
Сомневаюсь, что #include›stdio.h› даже скомпилируется...   -  person PhiLho    schedule 07.03.2011
comment
извини @PhiLho это #include‹stdio.h›   -  person Amit Singh Tomar    schedule 07.03.2011
comment
ваш второй пример не будет компилироваться. Пожалуйста, скопируйте/вставьте точный исходный код, который вы использовали.   -  person Alexandre C.    schedule 07.03.2011
comment
@Александри, я допустил ошибку, вставив код, теперь сделал его правильным ..   -  person Amit Singh Tomar    schedule 07.03.2011


Ответы (4)


первый:

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

после замены определения получаем:

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

теперь, поскольку у нас нет () в определении КВАДРАТ, мы получаем:

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

если вы хотите получить -25, вы должны определить SQUARE(x) как (x*x).

Изменить: добавить объяснение относительно второго примера.

printf("%d\n"FUN(val1,2));

еще раз, мы сначала должны заменить определение (напоминание: ## "сцепляет" строку определения - я не могу найти идеальных слов, чтобы объяснить это, поэтому просто взгляните на пример...):

printf("%d\n",val12);  [note: the comma (,) is missing - so it won't compile.]

поскольку значение val12 равно 20, это то, что вы получите.

смысл этих двух примеров состоит в том, чтобы помнить, что мы всегда должны сначала иметь дело с определениями (поскольку в «реальной жизни» компилятор (или препроцессор) делает это до времени выполнения)

Я надеюсь, что это помогает..

person SivGo    schedule 07.03.2011
comment
спасибо @SivGo за ваше объяснение, а также тот факт, что оператор / * имеет ассоциативность слева направо.... - person Amit Singh Tomar; 07.03.2011
comment
и не мог получить вторую проблему еще - person Amit Singh Tomar; 07.03.2011
comment
printf(%d\n,FUN(val1,2)); здесь значение val1 не собирается заменять на 10 ??? вот тут я запутался...думаю надо заменить на 10... - person Amit Singh Tomar; 07.03.2011
comment
на первом этапе выполняется определение, и только затем вы заменяете имя переменной ее значением, поэтому к тому времени, когда вы дойдете до этого, val1 больше не будет, только val12. - person SivGo; 07.03.2011
comment
понял, его предварительная обработка перед любой компиляцией - person Amit Singh Tomar; 07.03.2011

#define SQUARE(x) x*x

должно быть

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

Действительно, без круглых скобок 2*(s-u*t)/SQUARE(t) раскрывается как

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

который интерпретируется как

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

Что касается вашей второй проблемы, FUN(val1,2) будет расширен как val12 в соответствии с семантикой оператора ##. До сих пор не ясно, какой у вас замысел: строка printf будет пониматься как

printf("%d\n", val12);

который напечатает 20.

person Alexandre C.    schedule 07.03.2011
comment
Так же например два, (i##j) - person alternative; 07.03.2011
comment
Спасибо @Александр. это a=(2*(s-ut)/t)*t ; выражение соответствует #define SQUARE(x) xx , это то, что вы хотите сказать - person Amit Singh Tomar; 07.03.2011
comment
почему определение FUN таким образом: #define FUN(i,j) (i##j) решило бы проблему? - person SivGo; 07.03.2011
comment
@SivGo: цель второго примера не ясна. Теперь, когда ОП исправил свой код, я обновляю ответ. - person Alexandre C.; 07.03.2011

Для первого случая

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

перевел бы на

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

во время компиляции. Это распространенная ошибка, которую допускают с препроцессорами.

person Shamim Hafiz    schedule 07.03.2011

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

в c# at define используется для вызова текста, как он есть в параметре функции,

например, #define hai(s1) printf("%s=%s",#s1,s1);

       in main: i am calling as hai(tom); tom was initialized as "india" string.

вывод для этого tom=india, вызывающая строка tom печатается с помощью #.

аналогично ## используется, чтобы взять текст из аргумента функции, объединить их и вернуть значение объединенного идентификатора.

вышеприведенная программа имеет два аргумента va1 и 2. переданные i и j. затем va1 и 2 соединяются. и образуют va12.

va12 — это идентификатор, доступный со значением 20, поэтому возвращается 20.

person selvabharathi s    schedule 05.05.2019