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.