파일 범위에서 다양하게 수정 된 배열


85

내 ".m"파일의 최상위 수준에서 다음과 유사한 Objective-C 구현 파일 전체에서 사용할 상수 정적 배열을 만들고 싶습니다.

static const int NUM_TYPES = 4;
static int types[NUM_TYPES] = { 
  1,
  2, 
  3, 
  4 };

NUM_TYPES나중에 파일에서 사용할 계획 이므로 변수에 넣고 싶었습니다.

그러나 이렇게하면 오류가 발생합니다.

"파일 범위에서 다양하게 수정 된 '유형'"

나는 이것이 배열 크기가 변수 인 것과 관련이있을 수 있다고 수집합니다 (예 : 정수 리터럴을 넣을 때이 메시지를받지 못합니다 static int types[4]).

나는 이것을 고치고 싶지만, 아마 나는 그것에 대해 모두 잘못하고있을 것입니다 ... 여기에 두 가지 목표가 있습니다.

  1. 파일 전체에서 액세스 할 수있는 배열을 가지려면
  2. NUM_TYPES변수로 캡슐화 하여 파일의 다른 위치에 동일한 리터럴이 흩어져 있지 않도록

어떤 제안?

[편집] C FAQ에서 발견 : http://c-faq.com/ansi/constasconst.html


2
대신 정의로 수행하면 어떻게됩니까? #define kNUM_TYPES 4?
Jorge Israel Peña

그것은 작동합니다 ... 어떤 이유로 나는 어딘가에서 읽은 것을 기억하고 있다고 생각했기 때문에 전처리기를 사용하지 않으려 고 노력했지만 더 많은 조사를 수행 했으며이 경우 사용하지 않을 좋은 이유를 찾을 수 없었습니다. 전 처리기에서 객체를 생성하는 것이 바람직하지 않을 수 있다고 생각합니다 (예 :) @"An NSString literal"코드 조각에 문제가있는 유일한 점은 세미콜론이 필요 없다는 것입니다.
Sam

아 예, 알려 주셔서 감사합니다. 도와 드릴 수있어서 기쁩니다.
Jorge Israel Peña

답변:


62

이 경고의 이유 는 c의 const가 상수를 의미하지 않기 때문입니다. "읽기 전용"을 의미합니다. 따라서 값은 메모리 주소에 저장되며 잠재적으로 기계 코드에 의해 변경 될 수 있습니다.


3
정의 된 객체를 수정하는 것은 (포인터에서 const캐스트 const하고 값을 저장하는 것과 같이 ) 정의되지 않은 동작입니다. 따라서 이러한 개체의 값은 컴파일 시간 또는 런타임 상수입니다 (저장 기간에 따라 다름). C 표준에서 가능하다고 말하지 않기 때문에 상수 표현식에서 값을 사용할 수 없습니다. ( const대상 객체가 const동적 할당 없이 정의 되거나 동적으로 할당 된 경우 값을 버리고 저장하는 것이 허용됩니다 . 문자열 리터럴은 그렇지 const않지만 기록되지 않을 수 있습니다.)
jilles

3
@jilles "잠재적으로 기계 코드에 의해 변경 될 수 있음"은이 답변의 작성자가 "잠재적으로 C 코드에 의해 변경 될 수 있음"을 의미하지는 않습니다. 또한, 이것은 또 다른 매우 좋은 이유가 있습니다 extern. 현재 TU를 컴파일 할 때 값을 알 수 없는 다른 TU에 상수 가있을 수 있습니다 .

14
이 답변을 개선하는 방법은이 문제를 해결하는 방법을 보여주는 것입니다.
조지 스토커

32

어쨌든 다른 답변에 따라 전처리기를 사용하려는 경우 컴파일러가 NUM_TYPES자동으로 값을 결정하도록 할 수 있습니다 .

#define NUM_TYPES (sizeof types / sizeof types[0])
static int types[] = { 
  1,
  2, 
  3, 
  4 };

와, 정말 멋지네요 ... 그게 가능한지 몰랐어요. 이 계산의 비용은 무시할 만하다고 가정합니다. 컴파일러가 이것을 정적 값으로 최적화 할 수 있다고 가정해도 될까요?
Sam

2
예, sizeof이와 같은 객체 의 결과 는 컴파일 타임 상수입니다.
caf 2011


11

열거를 사용할 수도 있습니다.

typedef enum {
    typeNo1 = 1,
    typeNo2,
    typeNo3,
    typeNo4,
    NumOfTypes = typeNo4
}  TypeOfSomething;

4

다른 답변에서 이미 설명했듯이 constC에서는 변수가 읽기 전용임을 의미합니다. 여전히 런타임 값입니다. 그러나 enumC에서는를 실수 상수로 사용할 수 있습니다 .

enum { NUM_TYPES = 4 };
static int types[NUM_TYPES] = { 
  1, 2, 3, 4
};

3

Imho 이것은 많은 c 컴파일러의 결함입니다. 내가 작업 한 컴파일러는 주소에 "정적 const"변수를 저장하지 않고 코드에서 사용하는 것을 매우 상수로 대체한다는 사실을 알고 있습니다. 전 처리기 #define 지시문을 사용할 때와 정적 const 변수를 사용할 때 생성 된 코드에 대해 동일한 체크섬을 얻게되므로 확인할 수 있습니다.

어느 쪽이든 정적 const는 유형에 안전하므로 가능하면 #defines 대신 정적 const 변수를 사용해야합니다.


static const변수 의 주소를 사용할 수 있기 때문에 꽤 나쁘게 들립니다 . 설명하는 동작은 유효한 최적화 일 수 있지만 항상 작동 할 수있는 것은 아닙니다.
긴장 풀기

실제로 괜찮습니다. 가능한 경우 C 컴파일러가 const 전역 변수의 개별 사용을 상수 값으로 바꾸는 것은 괜찮습니다. 변수에 대한 모든 참조가 상수로 변환되면 컴파일러는이를 완전히 제거 할 수 있습니다. 어디에서나 주소를 사용하면 제거되지 않습니다. 언어 표준에 따라 C는 변수가 const인지 여부에 관계없이 크기가 변수 인 전역 배열을 허용하지 않습니다.
Evan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.