Objective-C에서 #define 대 const


81

저는 Objective-C를 처음 사용하며 const및 전처리 지시문 에 대해 몇 가지 질문이 #define있습니다.

첫째,을 사용하여 상수의 유형을 정의 할 수 없음을 발견했습니다 #define. 왜 그런 겁니까?

둘째, 그중 하나를 다른 것보다 사용하면 어떤 이점이 있습니까?

마지막으로 어떤 방법이 더 효율적이고 더 안전합니까?

답변:


107

첫째, #define을 사용하여 상수 유형을 정의 할 수 없다는 것을 발견했습니다. 그 이유는 무엇입니까?

왜? 그것은 사실이 아닙니다:

#define MY_INT_CONSTANT ((int) 12345)

둘째, 그중 하나를 다른 것보다 사용하면 어떤 이점이 있습니까?

예. #define컴파일이 시작되기 전에 교체되는 매크로를 정의합니다. const변수를 변경하려고하면 컴파일러가 오류를 표시하도록 변수를 수정하기 만합니다. a #define를 사용할 수 있지만 사용할 수없는 컨텍스트가 있습니다 const(최신 clang을 사용하여 찾는 데 어려움을 겪고 있지만). 이론적 const으로는 실행 파일에서 공간을 차지하고 메모리에 대한 참조가 필요하지만 실제로는 중요하지 않으며 컴파일러에 의해 최적화 될 수 있습니다.

consts는 s보다 훨씬 더 컴파일러 및 디버거 친화적 #define입니다. 대부분의 경우, 이것이 어떤 것을 사용할 것인지 결정할 때 고려해야 할 최우선 사항입니다.

사용할 수 #define있지만 사용할 수 없는 컨텍스트를 생각했습니다 const. 많은 .c파일 에서 사용하려는 상수가 #define있는 경우 헤더에 붙이면됩니다. 를 사용하면 constC 파일에 정의가 있어야하며

// in a C file
const int MY_INT_CONST = 12345;

// in a header
extern const int MY_INT_CONST;

헤더에. MY_INT_CONST정의 된 파일을 제외한 모든 C 파일에서 정적 또는 전역 범위 배열의 크기로 사용할 수 없습니다.

그러나 정수 상수의 경우 enum. 사실 그것은 애플이 거의 변함없이하는 일이다. 이것은 #defines와 consts 의 모든 장점을 가지고 있지만 정수 상수에 대해서만 작동합니다.

// In a header
enum
{
    MY_INT_CONST = 12345,
};

마지막으로 어떤 방법이 더 효율적이고 더 안전합니까?

#define내가 말했듯이 현대 컴파일러는 아마도 차이가 거의 없음을 보장하지만 이론적으로 더 효율적입니다. #define할당을 시도하는 것이 항상 컴파일러 오류라는 점에서 더 안전합니다.

#define FOO 5

// ....

FOO = 6;   // Always a syntax error

const컴파일러가 경고를 발행 할 수 있지만 s가 할당되도록 속일 수 있습니다.

const int FOO = 5;

// ...

(int) FOO = 6;     // Can make this compile

플랫폼에 따라 상수가 읽기 전용 세그먼트에 배치되고 C 표준에 따라 공식적으로 정의되지 않은 동작 인 경우 런타임에 할당이 여전히 실패 할 수 있습니다.

개인적으로 정수 상수 enum의 경우 다른 유형의 상수에는 항상 s를 사용 const합니다. 그럴 이유가없는 한 사용합니다.


나는 그것이 오래되었다는 것을 알고 있지만, 정의를 사용할 수있는 const를 사용할 수없는 한 인스턴스는 "NSNumber * const MY_NSNUM_CONSTANT = @ 5"를 사용하여 수행 할 수없는 "#define MY_NSNUM_CONSTANT @ 5"입니다
shortstuffsushi

#define은 const보다 실행 파일에서 더 많은 공간을 차지한다고 주장합니다. const는 한 번 저장되지만 텍스트 교체 일 뿐이므로 사용할 때마다 #define이 곱해집니다. 그러나 그 차이가 미미하기 때문에 나는 불필요하게 현학적 인 태도를 보이고 있습니다.
Ryan Ballantyne

@RyanBallantyne 나는 당신이 문자열 상수와 같은 것에 적합하다고 생각하지만 정수 상수에는 적합하지 않을 것이라고 생각합니다. 상수를 한곳에 저장하더라도 액세스하려면 적어도 int. 그러나 현대 컴파일러에서 어떤 차이가 있다면 매우 놀랍습니다.
JeremyP 2015

16

C 코더에서 :

A const는 내용을 변경할 수없는 변수입니다.

#define name value그러나,의 모든 인스턴스를 대체하는 전 처리기 명령입니다 name와 함께 value.

예를 들어,이면 컴파일 할 때 코드 #define defTest 5의 모든 인스턴스 defTest가로 대체됩니다 5.


11

동일한 의미가 아닌 #define과 const 명령어의 차이점을 이해하는 것이 중요합니다.

const

const일단 초기화되면 상수가되는 요청 된 유형에서 객체를 생성하는 데 사용됩니다. 이는 프로그램 메모리의 객체이며 읽기 전용으로 사용할 수 있음을 의미합니다. 프로그램이 실행될 때마다 개체가 생성됩니다.

#define

#define코드 가독성과 향후 수정을 용이하게하기 위해 사용됩니다. 정의를 사용할 때 이름 뒤에있는 값만 마스킹합니다. 따라서 직사각형으로 작업 할 때 해당 값으로 너비와 높이를 정의 할 수 있습니다. 그러면 코드에서 숫자 대신 이름이 있기 때문에 읽기가 더 쉽습니다.

나중에 너비 값을 변경하기로 결정하면 전체 파일에서 지루하고 위험한 찾기 / 바꾸기 대신 정의에서만 변경하면됩니다. 컴파일 할 때 전처리 기는 정의 된 모든 이름을 코드의 값으로 대체합니다. 따라서 시간 낭비가 없습니다.


7

다른 사람들의 의견 외에도 #define전처리 기가 컴파일러보다 먼저 오류를 잡기 때문에 사용 하는 오류 는 디버그하기가 매우 어렵습니다.


3

전 처리기 지시문이 눈살을 찌푸 리기 때문에 const. 전 처리기 지시문이 컴파일 전에 확인되기 때문에 전처리기로 유형을 지정할 수 없습니다. 글쎄, 할 수 있지만 다음과 같습니다.

#define DEFINE_INT(name,value) const int name = value;

그리고 그것을 사용하십시오

DEFINE_INT(x,42) 

컴파일러에서 다음과 같이 볼 수 있습니다.

const int x = 42;

첫째, #define을 사용하여 상수 유형을 정의 할 수 없다는 것을 발견했습니다. 그 이유는 무엇입니까?

내 첫 번째 스 니펫을 볼 수 있습니다.

둘째, 그중 하나를 다른 것보다 사용하면 어떤 이점이 있습니까?

일반적으로 const전 처리기 지시문 대신 사용하면 디버깅에 도움이되지만이 경우에는 그다지 도움이되지 않지만 여전히 그렇습니다.

마지막으로 어떤 방법이 더 효율적이고 더 안전합니까?

둘 다 효율적입니다. 매크로는 런타임 중에 변경할 수 없지만 변수는 변경할 수 있으므로 잠재적 으로 더 안전 할 수 있다고 말하고 싶습니다 .


const ...매크로를 사용하는 대신 입력 만하는 이유는 무엇 입니까?
Ed Heal

1
@EdHeal하지 않습니다. "#define을 사용하여 상수 유형을 정의 할 수 없음을 발견했습니다. 그 이유는 무엇입니까?"
Luchian Grigore

1
> pre-processor directives are frowned upon[인용 필요]
Ben Leggiero

다음과 같은 유형을 사용할 수 있다고 생각합니다 : #define myValue ((double) 2). 내가 이해하는대로 전처리 기는 "myValue"를 유형 정보를 포함하여 정의 문에서 그 뒤에 오는 것으로 대체합니다.
vomako

1

이전에 #define을 사용하여 한 가지 방법으로 더 많은 방법을 만들 수 있습니다.

 // This method takes up to 4 numbers, we don't care what the method does with these numbers.
 void doSomeCalculationWithMultipleNumbers:(NSNumber *)num1 Number2:(NSNumber *)num2 Number3:(NSNumber *)num23 Number3:(NSNumber *)num3;

그러나 나는 또한 3 개의 숫자와 2 개의 숫자만을 취하는 방법을 가질 수 있으므로 두 개의 새로운 방법을 작성하는 대신 #define을 사용하여 동일한 방법을 사용할 것입니다.

 #define doCalculationWithFourNumbers(num1, num2, num3, num4) \
         doSomeCalculationWithMultipleNumbers((num1), (num2), (num3), (num4))

 #define doCalculationWithThreeNumbers(num1, num2, num3) \
         doSomeCalculationWithMultipleNumbers((num1), (num2), (num3), nil)

 #define doCalculationWithTwoNumbers(num1, num2) \
         doSomeCalculationWithMultipleNumbers((num1), (num2), nil, nil)

제 생각에는 이것이 매우 멋진 일이라고 생각합니다. 바로 방법으로 이동하여 원하지 않는 공간에 nil을 넣을 수 있지만 라이브러리를 구축하는 경우 매우 유용합니다. 또한 이것은 방법입니다

     NSLocalizedString(<#key#>, <#comment#>)
     NSLocalizedStringFromTable(<#key#>, <#tbl#>, <#comment#>)
     NSLocalizedStringFromTableInBundle(<#key#>, <#tbl#>, <#bundle#>, <#comment#>)

완료되었습니다.

나는 당신이 상수로 이것을 할 수 있다고 믿지 않습니다. 그러나 상수는 컴파일 전에 해결되는 전 처리기 지시문이기 때문에 #define으로 유형을 지정할 수없는 것처럼 #define보다 이점이 있으며 #define으로 오류가 발생하면 디버그하기가 더 어렵습니다. 상수. 둘 다 장점과 단점이 있지만 모두 사용하기로 결정한 프로그래머에 따라 다릅니다. 내가 보여준 작업을 수행하기 위해 #define을 사용하고 유형을 지정해야하는 상수 변수를 선언하는 상수를 사용하여 둘 다 라이브러리를 작성했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.