c/c++ 배열이 컴파일타임에 크기가 정해지지 않아도 되나요?

mykldp의 이미지

C/C++ 에서 배열의 크기는 컴파일타임에 정해져야 하는 걸로 알고 있습니다.

예를 들면 아래와 같이 두 파일을 만들어 컴파일할 경우

test1.cpp

#include <iostream>

extern int size;

int main()
{
int arr[size];
return 0;
}

test2.cpp

int size = 10;

이런 경우 컴파일 에러를 내는 걸로 알고 있습니다. test1.cpp를 컴파일 할 때
컴파일러가 size의 값을 알 수 없기 때문이죠. VC++에서 테스트를 해보니
역시 컴파일에러를 내는군요... 그런데.
gcc 에서 해보니 에러가 안나네요. 배열이 아주 정상적으로 만들어지고 실행도
잘되네요....음....
컴파일 타임에 배열의 크기를 알 수 없는 여러가지 경우를 만들어서 컴파일 해봤는데 모두 VC++에서는 에러를 내고 gcc 에서는 에러가 나지를 안네요..
어떻게 된 걸까요? -_- 제가 c/c++ 배열에 대해 잘못 알고 있는 건지 아님
gcc의 경우에만 그런건지 모르겠네요. 고수님들 좀 알려주세요~~~

hilbertz의 이미지

자세한건 모르구여...
vc++에서 약간 문법이나 제공하는 함수가 틀린걸루 알구있습니다.
완벽하게 표준이 아니라는거죠. ^^;
예를들어 itoa()함수가 표준 c에는 없지만 vc++에서는 제공을 해주거든요.

Hi~ ^^/

nangchang의 이미지

C++ 문법은 어느 정도 유연성을 가지고 있습니다.

문법상에서 정확히 어떠해야 한다고 정해지지 않은 부분이 많죠.

제가 알기론 배열의 크기를 다이나믹하게 선언할 수 있느냐 아니냐

하는 부분이 정확하게 정의 되어 있지 않은걸로 알고 있습니다

(음.. 아닐수도 있어요..-_-a)

그래서 어떻게 구현하느냐에 따라 컴파일러마다 차이가 있을 수 있습니다.

VC++의 경우에는 허용하지 않고, GCC의 경우에는 허용을 하도록 되어있죠.

(잘 비교해 보면 컴파일러 마다 몇몇 차이점을 보실수 있을 겁니다.

그 예 중 하나로

for ( int i = 0; i < 10; i++ )
{
...
}

라고 했을 경우, VC++ 에서는 i가 for문 이후에도 살아있지만

GCC에서는 for문 내에서만 살아있죠.)

음.. 틀린게 있으면 지적해 주시길..

mykldp의 이미지

방금 gcc 매뉴얼에서 찾아봤는데

Arrays of Variable Length 는 gcc의 extension이랍니다.

ANSI C/C++에서는 자동 배열(automatic array)의 크기가 compile time에 정해져야 하는데

gcc에서는 그렇지 않아도 된다고 하는군요.

체스맨의 이미지

c 및 c++ 에도 적용되는 gcc extension 입니다.

이미 alloca 라는, stack 에 메모리를 동적으로 할당하는
함수가 있었구요. 내부적으로는 alloca 와 유사한 코드가
생성됩니다. 할당 속도 면에서 malloc 보다 빠릅니다.

하지만, 호환성이 떨어지고, 할당할 수 있는 메모리 크기가
한계가 있기때문에 되도록 표준적인 방법을 쓰는 게 좋습니다.

Orion Project : http://orionids.org

cinsk의 이미지

ISO C 표준에서는 가변 크기 배열에 대해 언급이 있습니다.

즉 이제는 C 표준인 것이죠.

따라서 다음과 같은 코드를 쓸 수 있습니다. (ISO C 표준에서 따옴)

#include <stddef.h>

size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}

mykldp의 이미지

아..이제 표준이 되었군요.

혹시 이를 지원하는 컴파일러들이 어떤 것들이 있는지 알 수 있을까요?

VC++ 6 의 경우는 지원되지 않는 것 같구요.

지원되는 컴파일러들을 알고 싶네요..

markboy의 이미지

1. Arrays of Variable Length는 ISO C99에 명시된 표준 spec. 입니다. 아직까지 ISO C99의 모든 spec을 구현한 C 컴파일러는 없습니다.

GCC의 경우 http://gcc.gnu.org/c99status.html 보시면 현재까지 구현된 내용에 대해서 보실 수 있습니다.

ISO C99 에 관한 문서는
http://www.cl.cam.ac.uk/~mgk25/volatile/ISO-C-FDIS.1999-04.pdf

2. C++ 이 문법에 유연성을 많이 가지고 있는 것은 사실이지만

for ( int i = 0; i < 10; i++ )
{
...
}

이 예의 경우는 VC가 C++ 표준 규약을 제대로 지키지 않은 문제입니다. C++ spec. 상 위의 int i 는 for의 scope 에서만 유효해야 합니다.

익명 사용자의 이미지

gcc에서는 위의 소스라면 할당전략 코드로 인식을 할수 있습니다.

그리고 스택을 할당하게 되는데

중요한 것은 할당이라고 해서 malloc 과 같은것이 아닙니다.

stack 을 사용하기 때문에

Disk swapping이 일어나지 않습니다.

즉 아무리 큰 메모리를 할당하더라도 스왑이 일어나지 않는거지요.

단점은 당연히 스왑공간의 메모리를 사용할수 없다는 거뿐이겠죠.

간단히 프롤로그에 다음과 같이 배열이 할당되죠....

void a(int size)
{
char d[size];
...
}

이런경우 gcc에서는 이를 인식하여 다음과 비스므레 코드를 생성할수
있다는 것을 알수 있습니다.

pushl %ebp
movl %esp, %ebp

subl 8(%ebp), %esp /* d 배열을 size인자를 이용해서 공간(스택) 확보 */
...

movl %ebp, %esp
pop %ebp

즉, 원래 가능한 문법이지만 다른 컴파일러에서 지원해주지 못하는것뿐.

- (주) 인포이큐 조재혁 - :D

lapex의 이미지

가변길이 배열의 사용시 문법상 주의할 사항이 있군여..

C99 일부 내용입니다.

간략하게 중요한 내용만 요약하자면(허잡 번역 -.-;;)

- 가변적으로 수정되는(VM) 타입의 선언은 반드시 block scope 나 function scope 내에 존재해야 한다

- static, extern 으로 선언된 struct, class 는 가변 길이 배열(VLA)을 쓸 수 없다

- VM 타입으로 선언된 id 는 struct, union 의 멤버가 될 수 없다.

샘플 코드를 보시면 쉽게 이해 되시라고 생각되는군여..

----
6.7.5.2 Array declarators

[#8] EXAMPLE 4 All declarations of variably modified (VM)
types have to be at either block scope or function prototype
scope. Array objects declared with the static or extern
storage class specifier cannot have a variable length array
(VLA) type. However, an object declared with the static
storage class specifier can have a VM type (that is, a
pointer to a VLA type). Finally, all identifiers declared
with a VM type have to be ordinary identifiers and cannot,
therefore, be members of structures or unions.

 
       extern int n;
       int A[n];                                       // Error - file scope VLA.
       extern int (*p2)[n];            // Error - file scope VM.
       int B[100];                             // OK - file scope but not VM.

       void fvla(int m, int C[m][m])   // OK - VLA with prototype scope.
       {
               typedef int VLA[m][m]   // OK - block scope typedef VLA.

               struct tag {
                       int (*y)[n];            // Error - y not ordinary identifier.
                       int z[n];                       // Error - z not ordinary identifier.
               };
               int D[m];                               // OK - auto VLA.
               static int E[m];                // Error - static block scope VLA.
               extern int F[m];                // Error - F has linkage and is VLA.
               int (*s)[m];                    // OK - auto pointer to VLA.
               extern int (*r)[m];             // Error - r had linkage and is
                                                       // a pointer to VLA.
               static int (*q)[m] = &B; // OK - q is a static block
                                                       // pointer to VLA.
       }


---
익명 사용자의 이미지

stack을 사용하는 것과 메모리 swapping은 관련이 없는 내용입니다.
메모리 swapping은 page replacement정책에 의해서 하는 것이고 stack&heap사용과는 완전 별개 입니다. mpin같은 API가 있긴 한데 stack 여부를 따져서 page를 고정하는 시스템은 본적이 없습니다.

minzkn wrote:
gcc에서는 위의 소스라면 할당전략 코드로 인식을 할수 있습니다.

그리고 스택을 할당하게 되는데

중요한 것은 할당이라고 해서 malloc 과 같은것이 아닙니다.

stack 을 사용하기 때문에

Disk swapping이 일어나지 않습니다.

즉 아무리 큰 메모리를 할당하더라도 스왑이 일어나지 않는거지요.

단점은 당연히 스왑공간의 메모리를 사용할수 없다는 거뿐이겠죠.

간단히 프롤로그에 다음과 같이 배열이 할당되죠....

void a(int size)
{
char d[size];
...
}

이런경우 gcc에서는 이를 인식하여 다음과 비스므레 코드를 생성할수
있다는 것을 알수 있습니다.

pushl %ebp
movl %esp, %ebp

subl 8(%ebp), %esp /* d 배열을 size인자를 이용해서 공간(스택) 확보 */
...

movl %ebp, %esp
pop %ebp

즉, 원래 가능한 문법이지만 다른 컴파일러에서 지원해주지 못하는것뿐.

- (주) 인포이큐 조재혁 - :D

purewell의 이미지

nangchang wrote:
그 예 중 하나로

for ( int i = 0; i < 10; i++ )
{
...
}

라고 했을 경우, VC++ 에서는 i가 for문 이후에도 살아있지만

GCC에서는 for문 내에서만 살아있죠.)

음.. 틀린게 있으면 지적해 주시길..

ㅡ_-) 위 예제는 VC의 버그로 알고 있습니다.

_____________________________
언제나 맑고픈 샘이가...
http://purewell.biz

익명 사용자의 이미지

주의할 것은, C에는 가변길이 배열이 있는데 C++에는 없다는 것입니다. C의 표준이 C++보다 더 최신이죠.

darkorb의 이미지

purewell wrote:
nangchang wrote:
그 예 중 하나로

for ( int i = 0; i < 10; i++ )
{
...
}

라고 했을 경우, VC++ 에서는 i가 for문 이후에도 살아있지만

GCC에서는 for문 내에서만 살아있죠.)

음.. 틀린게 있으면 지적해 주시길..

ㅡ_-) 위 예제는 VC의 버그로 알고 있습니다.

vc2005에서는 제대로 적용이 되더군요

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.