[c] “정적 const”vs“#define”vs“enum”

C의 아래 진술 중에서 어느 것이 더 나은가요?

static const int var = 5;

또는

#define var 5

또는

enum { var = 5 };



답변

필요한 가치에 따라 다릅니다. 당신 (그리고 지금까지 다른 사람들)은 세 번째 대안을 생략했습니다.

  1. static const int var = 5;
  2. #define var 5
  3. enum { var = 5 };

이름 선택에 관한 문제를 무시하면 다음과 같습니다.

  • 포인터를 주위에 전달해야하는 경우 (1)을 사용해야합니다.
  • (2)는 분명히 옵션이므로 포인터를 전달할 필요가 없습니다.
  • (1)과 (3) 모두 디버거의 심볼 테이블에 심볼이있어 디버깅이 쉬워집니다. (2)에 기호가 없을 가능성이 높으며 그 의미가 무엇인지 궁금해합니다.
  • (1) 전역 범위에서 배열의 차원으로 사용할 수 없습니다. (2)와 (3) 모두 가능합니다.
  • (1) 함수 범위에서 정적 배열의 차원으로 사용할 수 없습니다. (2)와 (3) 모두 가능합니다.
  • C99에서는이 모든 것을 로컬 어레이에 사용할 수 있습니다. 기술적으로 (1)을 사용하는 것은 VLA (가변 길이 배열)를 사용한다는 것을 의미하지만 ‘var’이 참조하는 차원은 물론 크기 5로 고정됩니다.
  • (1) 스위치 문과 같은 장소에서는 사용할 수 없습니다. (2)와 (3) 모두 가능합니다.
  • (1) 정적 변수를 초기화하는 데 사용할 수 없습니다. (2)와 (3) 모두 가능합니다.
  • (2) 전 처리기에서 사용하기 때문에 변경하고 싶지 않은 코드를 변경할 수 있습니다. (1)과 (3)은 모두 예상치 못한 부작용이 없습니다.
  • 프리 프로세서에 (2)가 설정되어 있는지 여부를 감지 할 수 있습니다. (1)도 (3)도 허용하지 않습니다.

따라서 대부분의 상황에서 대안보다 ‘열거’를 선호합니다. 그렇지 않으면 첫 번째 글 머리 기호와 마지막 글 머리 기호가 제어 요소가 될 가능성이 높으며 한 번에 두 가지를 모두 만족시켜야하는 경우 더 열심히 생각해야합니다.

C ++에 대해 묻는다면 매번 옵션 (1) (정적 const)를 사용합니다.


답변

일반적으로 말하면:

static const

범위를 존중하고 형식이 안전하기 때문입니다.

내가 볼 수있는 유일한주의 사항 : 명령 줄에 변수를 정의하려는 경우. 여전히 대안이 있습니다.

#ifdef VAR // Very bad name, not long enough, too general, etc..
  static int const var = VAR;
#else
  static int const var = 5; // default value
#endif

가능하면 매크로 / 줄임표 대신 유형이 안전한 대안을 사용하십시오.

매크로와 함께 가야하는 경우 (예 : __FILE__또는 __LINE__) 매크로 이름을 매우 신중하게 지정하는 것이 좋습니다. 명명 규칙에서 Boost 는 프로젝트 이름으로 시작하는 모든 대문자를 권장합니다 (여기서는 BOOST_ ), 라이브러리를 숙독하는 동안 (일반적으로) 그 뒤에 특정 영역 (라이브러리)의 이름과 그 뒤에 의미있는 이름이 붙는 것을 알 수 있습니다.

그것은 일반적으로 긴 이름을 만듭니다 🙂


답변

C에서는 구체적으로? 사용 : C에서 정답은 #define(해당되는 경우, 또는 enum)

const객체 의 범위 지정 및 타이핑 속성을 갖는 것이 유리하지만 , 실제로 constC의 객체 (C ++와 반대)는 실제 상수가 아니므로 대부분의 실제 경우에는 쓸모가 없습니다.

따라서 C에서 선택은 상수를 어떻게 사용할 계획인지에 따라 결정되어야합니다. 예를 들어, const int개체를 case레이블 로 사용할 수 없습니다 (매크로가 작동하는 동안). const int매크로를 작동하는 동안 객체를 비트 필드 너비로 사용할 수 없습니다 . C89 / 90에서는 const객체를 사용하여 배열 크기를 지정할 수 없습니다 (매크로가 작동하는 동안). C99에서도 VLAconst 가 아닌 배열 이 필요할 때 객체를 사용하여 배열 크기를 지정할 수 없습니다 .

이것이 당신에게 중요하다면 그것은 당신의 선택을 결정할 것입니다. 대부분의 경우 #defineC 에서 사용하는 것 외에는 선택의 여지가 없습니다 enum. C-에서 진정한 상수를 생성하는 다른 대안을 잊지 마십시오 .

C ++ const객체는 진정한 상수이므로 C ++에서는 const변형 을 선호하는 것이 거의 항상 좋습니다 ( staticC ++ 에서는 명시 적으로 필요하지 않음 ).


답변

차이 static const하고 #define있다는 이전의 메모리 사용 및 저장을 위해 나중에 사용하지 않는 메모리. 둘째,의 주소는 전달할 수 없지만의 주소 #define는 전달할 수 있습니다 static const. 실제로 그것은 우리가 어떤 환경에 있는지에 따라 다르며,이 두 가지 중에서 하나를 선택해야합니다. 둘 다 다른 상황에서 최선을 다하고 있습니다. 하나가 다른 것보다 낫다고 가정하지 마십시오 … 🙂

만약 그렇다면, Dennis Ritchie 는 최선을 다했을 것입니다 … hahaha … 🙂


답변

C #define에서는 훨씬 더 인기가 있습니다. 예를 들어 배열 크기를 선언하기 위해 해당 값을 사용할 수 있습니다.

#define MAXLEN 5

void foo(void) {
   int bar[MAXLEN];
}

ANSI C는 static const내가 아는 한이 문맥에서 s 를 사용할 수 없습니다 . C ++에서는 이러한 경우 매크로를 피해야합니다. 당신은 쓸 수 있습니다

const int maxlen = 5;

void foo() {
   int bar[maxlen];
}

static내부 연결은 const이미 [C ++에서만]에 의해 암시되기 때문에 제외하십시오 .


답변

constC 의 또 다른 단점은 다른를 초기화 할 때 값을 사용할 수 없다는 것 const입니다.

static int const NUMBER_OF_FINGERS_PER_HAND = 5;
static int const NUMBER_OF_HANDS = 2;

// initializer element is not constant, this does not work.
static int const NUMBER_OF_FINGERS = NUMBER_OF_FINGERS_PER_HAND
                                     * NUMBER_OF_HANDS;

컴파일러는 상수로 간주하지 않기 때문에 const에서도 작동하지 않습니다.

static uint8_t const ARRAY_SIZE = 16;
static int8_t const lookup_table[ARRAY_SIZE] = {
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; // ARRAY_SIZE not a constant!

const이 경우에는 타이핑을 사용하게되어 기쁩니다 . 그렇지 않으면 …


답변

도망 갈 수 있다면 static const 많은 장점이 있습니다. 일반적인 범위 원칙을 준수하고 디버거에서 볼 수 있으며 일반적으로 변수가 따르는 규칙을 따릅니다.

그러나 최소한 원래 C 표준에서는 실제로 일정하지 않습니다. 당신이 사용하는 경우 #define var 5, 당신은 쓸 수 int foo[var];선언으로,하지만 당신과 함께 컴파일러 확장 “를 제외하고 (그렇게 할 수 없습니다 static const int var = 5;. 이것은 ++은 C의 경우가 아니라 static const버전 어디서나 사용할 수 있습니다#define 버전 캔, 그리고 믿을 C99의 경우도 마찬가지입니다.

그러나 #define소문자 이름 으로 상수 이름을 지정하지 마십시오 . 번역 단위가 끝날 때까지 해당 이름을 사용할 수 있습니다. 매크로 상수는 사실상 고유의 네임 스페이스에 있어야하며, 일반적으로 접두사가있는 모든 대문자입니다.