문제
안녕 ,
Square (x)의 값이 49 인 이유를 이해하는 데 도움이 될 수 있습니까?
Visual C ++ 6.0을 사용하고 있습니다.
#define SQUARE(X) X * X
int main(int argc, char* argv[])
{
int y = 5;
printf("%d\n",SQUARE(++y));
return 0;
}
해결책
Neil Butterworth, Mark 및 Pavel이 옳습니다.
정사각형 (++ y)은 ++ y * ++ y로 확장되어 y 값의 두 배를 증가시킵니다.
발생할 수있는 또 다른 문제 : Square (A + B)는 A + B * A + B로 확장됩니다. (A + B) * (A + B)가 아니라 A + (B * A) + B입니다. #define square (x) ((x) * (x))는 약간 위험하지 않습니다. (이안 켐프는 그의 의견에서 먼저 썼다)
대신 다음과 같은 인라인 템플릿 함수 (런타임에서 효율적이지 않음)를 사용할 수 있습니다.
template <class T>
inline T square(T value)
{
return value*value;
}
작동하는 것을 확인할 수 있습니다.
int i = 2;
std::cout << square(++i) << " should be 9" << std::endl;
std::cout << square(++i) << " should be 16" << std::endl;
(글을 쓸 필요가 없습니다
square<int>(++i)
int 유형은 i에 암시 적이기 때문에)
다른 팁
매크로가 확장되기 때문에 :
++y * ++y
C ++에서 정의되지 않은 동작을 제공합니다. 결과는 무엇이든 할 수 있습니다. 이 잘 알려진 문제는 매크로 사용을 다루는 괜찮은 교과서에서 다루어야합니다. 어느 것을 사용하고 있습니까?
매크로는 텍스트 대체를 수행하므로 당신이 쓴 코드가 확장됩니다.
printf("%d\n",++y * ++y );
그리고 운영 순서는 정의되지 않은 동작이므로 컴파일러는 2 단위를보고 곱셈을 보게됩니다.
따라서 컴파일러가 인라인을 확장 할 수 있으므로 실행하는 데 더 오래 걸리지 않는 함수를 사용하는 데 더 잘 조심하십시오.
둘째, 변수를 증가시키고 사용하면 어떻게 될지 가정하지 마십시오.
매크로는 기능이 아닙니다. 프로그램의 텍스트 만 변경합니다. 이 작업이 호출됩니다 전처리 코드가 컴파일되기 전에 자동으로 실행됩니다. 사람들은 시간을 절약하고 소스 코드에 약간의 변동성을 소개하기 위해 매크로를 작성합니다.
당신이 쓸 때 SQUARE(x)
, 실제 funciton 호출이 발생하지 않으며 텍스트 만 수정됩니다. 수술은 꽤 멍청하므로 귀하와 같은 경우 추가 예방 조치를 취해야합니다. 사건에 대한 설명은 다른 답변을 참조하십시오.