문제

이전에는 질문 내가 좋은 대답이라고 생각했던 것은 제안된 매크로 사용에 대해 투표에서 제외되었습니다.

#define radian2degree(a) (a * 57.295779513082)
#define degree2radian(a) (a * 0.017453292519)

인라인 함수 대신.초보자 질문인 점 양해 부탁드립니다만, 이 경우 매크로가 왜 그렇게 나쁜가요?

도움이 되었습니까?

해결책

매크로에는 몇 가지 매우 나쁜 점이 있습니다.

텍스트 처리 중이며 범위가 지정되지 않았습니다.만약 너라면 #define foo 1, 이후의 모든 사용 foo 식별자로는 실패합니다.이로 인해 이상한 컴파일 오류와 찾기 어려운 런타임 버그가 발생할 수 있습니다.

그들은 일반적인 의미의 논쟁을 받아들이지 않습니다.두 가지를 사용하는 함수를 작성할 수 있습니다. int 인수는 한 번 평가되고 그 이후에는 값이 사용되기 때문에 최대값을 반환하고 최대값을 반환합니다.이를 위해 매크로를 작성할 수 없습니다. 왜냐하면 매크로는 적어도 하나의 인수를 두 번 평가하고 다음과 같은 오류로 실패하기 때문입니다. max(x++, --y).

일반적인 함정도 있습니다.여러 문을 제대로 작성하기가 어렵고 불필요한 괄호가 많이 필요할 수 있습니다.

귀하의 경우에는 괄호가 필요합니다.

#define radian2degree(a) (a * 57.295779513082)

될 필요가있다

#define radian2degree(a) ((a) * 57.295779513082)

그리고 당신은 여전히 ​​함수를 작성하는 사람을 밟고 있습니다. radian2degree 일부 내부 범위에서는 해당 정의가 자체 범위에서 작동할 것이라고 확신합니다.

다른 팁

다른 답변의 대부분은 예제가 일반적인 매크로 사용 결함을 갖는 방법을 포함하여 매크로가 사악한 이유에 대해 논의합니다. Stroustrup의 테이크는 다음과 같습니다. http://www.research.att.com/~bs/bs_faq2.html#macro

그러나 당신의 질문은 매크로가 여전히 어떤 좋은지 묻는 것이 었습니다. 매크로가 인라인 함수보다 더 나은 곳이 있으며, 그와 같은 인라인 함수로 단순히 수행 할 수없는 일을하는 곳이 있습니다.

  • 토큰 붙여 넣기
  • 라인 번호 또는 그에 따라 오류 메시지 작성을 위해 assert())
  • 표현이 아닌 것들을 다루는 것 (예 : 얼마나 많은 구현 offsetof() 유형 이름을 사용하여 캐스트 작업을 만듭니다)
  • 배열 요소를 얻는 매크로 (배열 이름이 포인터로 너무 쉽게 붕괴되므로 함수로 수행 할 수 없습니다)
  • 템플릿을 사용할 수없는 C에서 'Type Polymorphic'기능과 같은 제품 생성

그러나 인라인 기능이있는 언어를 사용하면 매크로의 일반적인 사용이 필요하지 않아야합니다. 인라인 함수를 지원하지 않는 C 컴파일러를 다룰 때 마크로를 사용하는 것을 꺼려합니다. 그리고 가능한 경우 유형의 공유 기능을 만들기 위해 사용하지 않으려 고 노력합니다 (대신 유형 표시기를 사용하여 여러 기능을 작성).

나는 또한 명명 된 숫자 상수에 열거를 사용하는 것으로 옮겼습니다. #define.

이 특정 매크로의 경우 다음과 같이 사용하면 다음과 같이 사용합니다.

int x=1;
x = radian2degree(x);
float y=1;
y = radian2degree(y);

유형 검사는 없으며 x, y는 다른 값을 포함합니다.

또한 다음 코드입니다

float x=1, y=2;
float z = radian2degree(x+y);

번역 될 것이기 때문에 당신이 생각하는 것을하지 않을 것입니다.

float z = x+y*0.017453292519;

대신에

float z = (x+y)+0.017453292519;

예상 결과입니다.

이것들은 ANS 오용 매크로가 가질 수있는 오해의 몇 가지 예일뿐입니다.

편집하다

이것에 대한 추가 토론을 볼 수 있습니다 여기

매크로는 비교적 종종 남용되며 예에서 볼 수 있듯이이를 사용하여 쉽게 실수 할 수 있습니다. Radian2degree (1 + 1) 표현을 취하십시오.

  • 매크로를 사용하면 1 + 1 * 57.29로 확장됩니다 ... = 58.29 ...
  • 함수를 사용하면 원하는 것이 될 것입니다. 즉 (1 + 1) * 57.29 ... = ...

더 일반적으로, 매크로는 악이기 때문에 악합니다 기능처럼 보입니다 그래서 그들은 당신이 기능처럼 그것들을 사용하도록 속입니다. 그러나 그들은 그들 자신의 미묘한 규칙을 가지고 있습니다. 이 경우, 올바른 방법은 (a 주변의 주변에 주목하는) 다음과 같습니다.

#define radian2degree(a) ((a) * 57.295779513082)

그러나 인라인 기능을 고수해야합니다. 사악한 매크로와 그 미묘함의 더 많은 예를 보려면 C ++ FAQ 라이트의 링크를 참조하십시오.

가능하면 항상 인라인 기능을 사용하십시오. 이들은 TypeSAFE이며 쉽게 재정의 할 수 없습니다.

정의는 정의되지 않은 레드테이션 될 수 있으며 유형 확인이 없습니다.

컴파일러의 사전 처리기는 지친 일이므로 영리한 트릭에 대한 끔찍한 후보입니다. 다른 사람들이 지적했듯이, 컴파일러가 매크로에 대한 의도를 오해하기 쉽고, 매크로가 실제로 무엇을 할 것인지 오해하기 쉽지만 가장 중요한 것은 디버거에서 매크로에 들어갈 수는 없습니다!

매크로는 변수 또는 스칼라 이상을 통과 할 수 있기 때문에 사악하며 원치 않는 동작으로 해결할 수 있습니다 (A와 B 사이의 최대를 결정하기 위해 최대 매크로를 정의하지만 A ++와 B ++를 매크로로 전달하고 어떻게되는지 확인하십시오. ).

어쨌든 함수가 인쇄되면 함수와 매크로 사이에 성능 차이가 없습니다. 그러나 함수와 매크로 사이에는 몇 가지 유용성 차이가 있으며, 이들은 모두 함수를 사용하는 선호입니다.

매크로를 올바르게 구축하면 문제가 없습니다. 그러나 함수를 사용하면 컴파일러가 매번 올바르게 수행합니다. 따라서 함수를 사용하면 잘못된 코드를 작성하기가 더 어려워집니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top