2008-11-23 6 views
17

정수형 매개 변수에 따라 배열의 크기가 인 간단한 함수가있다.C++ 배열 크기에 따라 함수 매개 변수가 달라진다. 컴파일 오류가 발생한다.

void f(int n){ 
     char a[n]; 
    }; 

    int main() { 
     return 0; 
    } 

이 코드 조각 GNU C++에서 잘 컴파일,하지만

MSVC 2005 년에 나는 다음과 같은 컴파일 오류가 얻을 :

.\main.cpp(4) : error C2057: expected constant expression 
    .\main.cpp(4) : error C2466: cannot allocate an array of constant size 0 
    .\main.cpp(4) : error C2133: 'a' : unknown size 

이 문제를 해결하기 위해 내가 무엇을 할 수 있는가?

는 스택에서 할당

답변

29

Gnu 컴파일러가 C++ 언어를 확장 한 것을 알게되었습니다. 이 경우 Visual C++가 완전합니다. C++의 배열은 컴파일 타임 상수 식인 크기로 정의해야합니다.

가변 길이 배열이라고하는 해당 언어에 대한 1999 년 업데이트에서 C에 추가 된 기능이 있습니다. C99을 지원하는 C 컴파일러를 찾을 수 있다면 쉽지 않습니다. 그러나이 기능은 표준 C++의 일부가 아니며 C++ 표준의 다음 업데이트에서 추가되지 않습니다.

C++에는 두 가지 솔루션이 있습니다.

char *a = new char [n]; 

내 대답을 쓰는 동안은, 또 다른 하나는 _alloca를 사용하는 제안을 게시 : 첫 번째, 두 번째는 단지 연산자 new []를 사용하는 것입니다, 성병 : 벡터를 사용하는 것입니다. 나는 그것을 강력히 추천 할 것이다. 컴파일러에 따라 다른 비표준이 아닌 이식성이없는 메서드를 다른 컴파일러와 교환해야합니다.

+1

그래,하지만, "new"가하는 힙에서 할당하는 것은 OP가하려고하는 스택에서 할당하는 것과 많이 다르다. (성능에 민감한 코드 일 수 있습니다.) –

+0

잠시 성능에 대한 걱정은별로 없지만 작동하는 것이 자연 스럽다고 생각했지만 C++ 표준의 일부가 아니라면 이해했습니다 – xxxxxxx

+0

Re : _alloca : OP는 MSVC에서 작동하는 새 코드를 사용하지 않고 동일한 코드를 가져 오는 것에 대해서만 질문했습니다. –

9

귀하의 방법 A g ++ 확장이다 (나는/삭제 새로운 사용하지 않고, MSVC이 작품을 만들기에 관심이 있어요). MSVC에서 해당 작업을 수행하려면, 당신은 _alloca 사용해야합니다

char *a = (char *)_alloca(n); 
+0

오, 그래서 스택에 할당합니다! 그게 놀랍습니다 :) 고마워요! – xxxxxxx

+1

alloca 맨 페이지의이 주석에 유의하십시오. 버그 alloca 함수는 기계 및 컴파일러에 따라 다릅니다. 많은 시스템에서 구현은 버그가 있습니다. 그 사용은 권장하지 않습니다. –

+0

그래,하지만 MSVC에서는 OP가 자신의 코드를 작동 시키려고 노력한 것이 확실하다. 나는 수년간 나 자신을 사용 해왔다. –

2

당신은 새 사용할 수/힙에/무료 메모리를 할당 삭제합니다. char [n]을 사용하는 것보다 속도가 느리고 오류가 발생하기 쉽지만 C++ 표준의 일부가 아닙니다. 슬프게도.

new []를 사용하는 경우 예외가 발생하지 않도록 boost 클래스의 배열 클래스를 사용할 수 있습니다. delete []는 범위를 벗어날 때 에서 자동으로 호출됩니다. 당신이을 경우 대신 C의 C99 코드로 컴파일, 문자 [N]을 사용하려면

void f(int n) { 
    std::vector<char> a; 
    a.resize(n); 

    /* Code here. */ 
} 

++ :

void f(int n) { 
    boost::scoped_array<char> a(new char[n]); 

    /* Code here. */ 
} 

당신은 또한) 일부 바이트를 표준 : : 벡터 및 예약을 (사용할 수 있습니다 암호.

어떤 이유로 든 스택에 데이터를 할당해야하는 경우 MSVC 라이브러리 등에서 제공되는 _alloca 또는 _malloca/_freea를 사용하십시오.

+0

네,하지만 MSVC가 실패하는 동안 g ++에 문제가없는 이유를 모르겠습니다. – xxxxxxx

+0

할당이 잘못되었습니다. 힙에서. 그는 g ++ 버전이하는 스택에 할당하려고합니다. MSVC가 원래 버전을 컴파일하지 않는 이유는 g ++ 확장이기 때문입니다. –

+0

그는 MSVC와 함께 스택에 넣을 수 없습니다. 그는 힙에 가지고 있거나 일정한 크기로 만들 수 있습니다. MSVC를 사용하여 스택에 가변 크기의 배열을 할당 할 방법이 없습니다. –

5

표준이 아닌 것을 사용 중입니다. 실제로 그것은 표준 C이지만 C++는 아닙니다. 얼마나 특이한가!

런타임 스택 크기의 스택 배열은 C++의 일부가 아니지만 C의 최신 표준 인 C99의 일부입니다.그것이 일부 컴파일러가 얻는 반면, 그렇지 않은 컴파일러도 있습니다. 나는 컴파일러 호환성 문제를 피하기 위해 그것을 사용하지 말 것을 권한다.

이 기능의 대체 구현은 strager가 게시 한 new 및 delete를 사용합니다.

+1

전혀 "특이하지 않다"..! –

1

일반적으로 C에서 (다른 사람이 지적한대로 C99 컴파일러 제외) 및 C++에서 스택에 메모리를 할당하려면 컴파일 할 때 할당하려는 크기를 알아야합니다. 로컬 변수는 스택에 할당되므로 런타임에 함수 매개 변수에 따라 길이가 다른 배열이이 규칙을 위반합니다. 대신되는,

 

char *a = new char [n]; 

A는 여전히 스택에 할당 된 로컬 변수이다 클라인은 "새로운"연산자를 사용하여이 문제를 해결하는 하나의 방법임을 지적하고 정확 전체 배열 (가변 길이를 가짐)은 배열에 대한 포인터 일뿐입니다 (항상 같은 크기이므로 컴파일 타임에 알려짐). 배열은 일반적으로 스택의 대응 부분을 재생하는 힙 (heap)에 할당됩니다. 스택은 컴파일시 알려진 크기의 항목을위한 것이고 힙은 컴파일 시간에 알 수없는 크기의 항목을위한 것입니다.

1

어레이가 아닌 vector<>을 사용하는 것이 합리적일까요? 또는 char *을 대체하기 때문에 std::string입니까? 그것들은 런타임 사이징과 잘 작동하지만, 사용하지 않는 다른 이유가있을 수 있습니다.

2

가변 길이 어레이가 C99에 도입되었습니다. gcc에서는 지원되지만 msvc에서는 지원되지 않습니다. MSVC 팀원에 따르면 Microsoft는 c/C++ 컴파일러에서이 기능을 지원할 계획이 없습니다. 그는 이러한 경우 std :: vector를 사용하도록 제안했습니다.

C99에서는 스택에 할당 된 배열이 필요하지 않습니다. 컴파일러는 힙에 할당 할 수 있습니다. 그러나 gcc는 스택에 배열을 할당합니다.