gcc와 MS VC++과 볼랜드 C는 다르다?

corone의 이미지

다음의 소스가 gcc와 MS VC++에서는 정상적으로 컴파일되고 출력되지만
볼랜드 C(혹은 터보C)에서는 에러를 일으킵니다.

#include

int main()
{
int ary1[4]={1,2,3,4};
int ary2[4]={11,12,13,14};
int ary3[4]={21,22,23,24};
int *ptr_ary[3]={ary1,ary2,ary3};
int i,j;

/* ptr_ary[0]=ary1;
ptr_ary[1]=ary2;
ptr_ary[2]=ary3;
*/
for(i=0 ; i<3 ; i++) {
for(j=0 ; j<4 ; j++) {
printf("%5d ", ptr_ary[i][j]);
}
puts(" ");
}
return 0;
}

Illegal initialization in function main 컴파일 에러

아래 코드 한줄이 에러를 일으키는데 아래 코드를 없애고
주석을 제거하면 정상적으로 컴파일됩니다.

int *ptr_ary[3]={ary1,ary2,ary3};

gcc와 MS VC++와 볼랜드 C의 컴파일러는 많이 다릅니까?
어떻게 다르고 위의 소스는 볼랜드 C에서 왜 에러가 난것입니까?
아시는 분 명쾌한 설명 부탁드립니다.

corone의 이미지

for문의 (i는 3보다 작다)와 (j는 4보다 작다)에서
"작다"기호는 태그라서 그런지
안먹혀서 대신 글로 썼습니다ㅡ.ㅡ;;
그 부분은 소스에서 이상없습니다

혹시 소스 복사하시려면 그 부분을 수정해주시기 바랍니다..

세이군의 이미지

C코드 부분은 <code> </code>안에 넣어주시면 문제없이 표시 가능합니다.
원문을 이 방법으로 수정하여 주십시요.

한 걸음 더 가까이

corone의 이미지

아 그렇군요
좋은 팁 가르쳐주셔서 감사합니다
설명하신대로 수정하였습니다

winner의 이미지

Borland C 혹은 Turbo C 라고 하셨는데 설마 Turbo C 2.01 을 말하나요?

lowid의 이미지

으흠... 전에도 이 쓰레드...(VC와 gcc 컴파일러의 차이점)
와 관련된 내용..kldp에서 인가 본거 같은데...
확실히 제목이 기억이 안나네요 ;

---------------------------------------------
아치리눅스좀 써주세요
-> 아치리눅스 유저 좀 꼬셔오세요. 1인당 10명!

corone의 이미지

답변주신 모든 분들께 감사합니다.
제가 가장 알고 싶은 것은
gcc와 MS VC++와 볼랜드 C++의 차이라기 보다는
위의 코드가 왜 볼랜드 C++에서는 에러가 나는지 설명해 주실 수 있으신지 입니다..

dasomoli의 이미지

어떤 에러가 나는지 메시지도 적어주시면 좋을 것 같습니다.
---------------------------------------------------------
*경고* 아바타 따라하지 마세요!!
dasomoli = DasomOLI = Dasom + DOLI = 다솜돌이
다솜 = 사랑하옴의 옛 고어.
Developer! ubuntu-ko! 다솜돌이 정석



dasomoli의 블로그(http://dasomoli.org)
dasomoli = DasomOLI = Dasom + DOLI = 다솜돌이
다솜 = 사랑하옴의 옛 고어.
Developer! ubuntu-ko! 다솜돌이 정석
corone의 이미지

Illegal initialization in function main

본문에 이미 에러 메세지 적었습니다
글을 읽어 주세요

임종규의 이미지

배열의 선언시에 배열멤버로 이전에 선언한 변수명을 사용시에 에러가 나더군요...

이유는 저도 모르겠습니다. 원래 안되는건지 vc 에서는 되던데...
gcc 에서는 안해봤구요...

어떤게 표준인지도 모르겠네요 ㅠㅠ

그때 급하게 문제만 해결할려고 해서 일단 변수 따로 지정하고.. 배열값에 값을 지정해서 해결했는데..

/* How to Love Others */
while(GetDepth(Love) < Enough) DoLove();

cinsk의 이미지

ANSI C라고 알려져있는 C89 표준은 정적 변수나 배열이나 구조체/union와 같은 타입을 초기화할 때 쓸 초기값이 상수식(constant expression)이어야 한다고 말하고 있습니다. 따라서 ptr_ary의 초기값은 상수식이 아니므로 에러가 납니다. 참고로, 지역 변수(automatic variable)의 주소는 상수식이 아닙니다.

ISO C 표준이라고 알려져 있는 C99 표준은 정적 변수일 때에만 상수식을 써야 한다고 말하고 있습니다. 즉 배열/구조체/union과 같은 타입에 대해서는 특별히 다루지 않았습니다. 즉, 상수식이 아니어도 됩니다.

Turbo C나 Borland C는 C99 표준 이전에 나온 컴파일러이므로, 당연히 에러가 날 것이며, 최신 GCC는 C99의 기능을 거의 포함하고 있으므로 컴파일될 것입니다. GCC의 표준 선택 옵션을 사용하면 이 결과를 더욱 자세히 알 수 있습니다.

$ gcc -std=c89 -pedantic -Wall tmp.c   # ANSI C 표준으로 컴파일
tmp.c: In fucntion 'foo':
tmp.c:6: warning: initializer element is not computable at load time
$ _

$ gcc -std=c89 -pedantic -Wall tmp.c   # ISO C 표준으로 컴파일
$ _

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

godmode2k의 이미지

혹시 이건 어떻게 되는지요...

char** str;
str[0] = new char[5];
memset( str[0], 0x00, sizeof(str[0]) );
strncpy( str[0], "test", 5 );
 
cout << "str[0] = " << str[0] << endl;

gcc 로 compile 해보면 "test" 라고 출력이 됩니다.

vc++ 6.0 (SP5) 로 compile 해보면

warning C4700: local variable 'str' used without having been initialized

이라는 error 가 납니다.

gcc 는 egcs-2.91.66 입니다.
물론 그 이후 버전에서도 잘 동작 합니다.

정확히 찾아보지는 않았지만 gcc extension 인지요 ?

winner의 이미지

잘못된 source 인데...

그전에 이건 C 가 아니라 C++ 군요.
g++ 의 compile option 이 어떻게 되었었는지.?
g++ 가 아무 경고를 안냈나요?

str[0] = new char[5];
위부분이 Visual C++ 6 의 경고 message 와 같은 잘못이 있습니다.

Visual C++ 6 는 경고만 냈으므로 분명 실행 file 은 만들어졌을 겁니다.
error 가 났다는 것은 실행시에 났다는 것인가요?

어찌되었든 잘못된 source 입니다.

godmode2k의 이미지

g++ 에서 테스트를 했었구요. (g++ -o test test.cpp)

vc++ 6.0 에서 warning message 와 함께 binary 는 만들어 졌습니다.
실행하면 하시죠? 당연히 error 가 났구요... 아래부분에서...

str[0] = new char[5];

g++ 에서는 warning 이 나지 않고 실행도 잘 되었습니다.
근본적으로 잘못된 code 인건 맞으나 g++ 에서는 잘 동작하는게 이상합니다.

delete 도 vc++ 6.0 과 g++ 에서 문제도 있구요. (2차원 pointer)

그냥 된다고 생각해서 작성하는것 보다는 각 compiler 의 특성(?)을 잘 알아야 할 듯 싶어서...

이상하군요... reply 하기 전에 test 를 다시 한번 해보니 (다른 환경: ubuntu 6.06 Dapper Drake)
이전엔 이 환경에서도 잘 동작을 하던게 오늘은 또 안되네요... 위의 코드 부분에서 segmentation fault 가 나네요...

음.. 다시 편집...
cygwin 에서의 g++ 에서는 또 동작을 하는군요...

$ g++ --version
g++ (GCC) 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)

 1 #include <iostream>
 2
 3 using namespace std;
 4 int main(void) {
 5     char** str;
 6
 7     str[0] = new char[5]; // 참고로 str[0] 하나만 allocation 해도 결과는 error 없이 출력됩니다.
 8     str[1] = new char[5];
 9
10     memset( str[0], 0x00, sizeof(str[0]) );
11     strncpy( str[0], "test", 5 );
12
13     memset( str[1], 0x00, sizeof(str[1]) );
14     strncpy( str[1], "best", 5 );
15
16     cout << "str[0] = " << str[0] << endl;
17     cout << "str[1] = " << str[1] << endl;
18
19     if( str ) {
20         for( int i=0; i<2; i++ )
21             delete [] str[i];
22
23         cout << "deleted..." << endl;
24     }
25
26     return 0;
27 }

결과는 다음과 같습니다.

$ ./test
str[0] = test
str[1] = best
deleted...

음... 계속 편집을 하게 되는군요.
ubuntu 6.06 Dapper Drake (g++ 4.0.3)에서 다시 위의 code 를 다시 실행을 해보니 실행이 되는군요.
str[0], str[1] 을 같이 allocation 한 다음 compile 해서 error 없는 결과를 확인한 후(실행)
str[1] 을 빼고 다시 recompile 해보니 error 없이 실행이 되는군요.

음...

lacovnk의 이미지

Quote:
이상하군요... reply 하기 전에 test 를 다시 한번 해보니 (다른 환경: ubuntu 6.06 Dapper Drake)
이전엔 이 환경에서도 잘 동작을 하던게 오늘은 또 안되네요... 위의 코드 부분에서 segmentation fault 가 나네요...

그런 코드를 보고 "잘못된 코드" 혹은 "동작 안하는 코드"라고 그냥 하는 겁니다..

왜 가끔은 되는 거지? 라고 탐구는 하면 더 많은 건 알겠지만요 :) 실제 언어나 컴파일러 구현을 더 알 수 있겠지요. 지금 궁금해하시는 것 처럼..

doldori의 이미지

Quote:

str[0], str[1] 을 같이 allocation 한 다음

str은 allocation 하셨나요? :-)
godmode2k의 이미지

str 은 allocation 하지 않았습니다.
str[0] 과 str[1] 만.

doldori의 이미지

음... 좀 난감하군요. ^^;
당연히 str도 allocation(초기화)을 해야지요.

char** str = new char*[2];
 
// ...
 
delete [] str;

godmode2k의 이미지

하지만 그렇게 하지 않아도 g++ 에서 동작을 하기에 이의를 제기한 것입니다.

vc++ 6.0 에서는 당연히 실행시 error 가 나구요.
하지만 g++ 에서는 실행시 왜 error 가 나지 않는지 궁금합니다.

doldori의 이미지

아, 질문 내용을 잘못 이해했습니다.
답은 저도 모르겠습니다.
그냥 그날의 운세 탓으로 추측합니다만. :-)

doldori의 이미지

winner의 이미지

어찌되었든 compile 할 때 -Wall option 만 넣어도 경고는 뜰거라고 생각합니다.
좀더 tight 하게 option 을 넣어보도 좋을 거 같습니다.
g++ -ansi -Wall -pedantic 으로 말이죠.

godmode2k의 이미지

말씀하신 option 을 줘서 해도 clue 가 나오지 않네요...

Cygwin 에서
 
$ g++ -ansi -Wall -pedantic -o test test.cpp

error 없이 잘 실행이 됩니다.

이러니 점점 더 궁금해 지네요...

kslee80의 이미지

프로그램 코드 자체로는 문법적 오류가 없기 때문에 컴파일시에는 에러가 나지 않는게 맞고....

현재 프로그램 코드 로직상에 오류가 있는건 인지하고 계시겠죠?
(이미 다른 분이 지적하신것처럼, str 의 공간을 할당해 준 이후에 str[0], str[1] 의 공간을 할당해야 합니다)

이런 경우, 프로그램 실행이 아무런 문제없이 잘 실행될수도 있고, Segmentation fault 를 내면서 죽을 수도 있습니다.

현재 문제는 str 에 공간을 할당해 주지 않은 상태로 str 을 사용하고 있는것이며,(str[0], str[1] 이라고 하는것 자체가 str 의 사용이죠)
아무런 문제없이 실행되거나, 혹은 Segmentation fault 를 내는 것은
프로그램 실행시에 str 에 들어가 있는 쓰레기 값에 따라서 틀려지게 됩니다.
str 에 들어가 있는 쓰레기 값이 우연찮게도 프로세스가 자유롭게 사용할 수 있는 메모리 주소값을 가진다면
프로그램이 아무런 문제없이 수행될 테지만,
프로세스가 사용할 수 없는 메모리 주소값을 가진다면 Segmentation fault 를 내면서 죽게 되겠죠.

이러한 프로그램 코드는 제아무리 실행이 정상적으로 되더라도 잘못된 코드이며, 지양해야 하는 것입니다.

godmode2k의 이미지

네, 저도 위에 작성한 코드에 오류가 있다는건 잘 알고 있습니다.
(일부러 그렇게 해놓고 테스트를 한걸요...)

test 시에 win32 와 gnu/linux 에서의 차이점이 있었습니다.
(몇가지가 있지만 대표적인게 위의 코드가 linux 에선 실행이 되었다는점.)
테스트 해보면서 나름대로 얻게 되는것도 있었구요.

아무튼 답변 감사드립니다. ^___^

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.