추억속의 버그 : C, C++

geekforum의 이미지

프로그램 짜면서 버그한번 없었던 사람은 아마 없겠죠. 아무리 실력있는 사람이라도 초보시절은 있었을 테고 그 실력까지 올라가기 위해 무지하게 많은 버그들을 양산해 냈을 거라는 생각이 듭니다. 마찬가지로, 아무리 좋은 프로그램이라도 버그가 없다고 확신할 수 있는 프로그램 역시 거의 없겠죠.

프로그래머로서 오늘도 버그와 싸우고 있는 여러분들...여러분들은 과연 어떤 버그를 만들어 냈었는지요? 누구나 한번쯤은 양산해 보았을 친근한(?) 버그들이나 여러분의 기억속에 추억으로 남아있는 버그가 있으면 이야기해 보자고요....

* 관리자 코멘트(webmaster):
일단 이번에는 C, C++언어에서 발생했던 버그로 한정합니다. Java등 다른 언어에 대한 버그는 다음에 다시 다루도록 하겠습니다. :-)

익명 사용자의 이미지

저같으면 저 함수를 쓰기전에 저함수 작성한 사람부터 갈구겠습니다.

익명 사용자의 이미지

실행속도 최적화라는 미명아래
비논리적인 코드를 권장하는 것은
아주 나쁜사람입니다.

익명 사용자의 이미지

에구구... 오타있습니다.

s/strcpy/strncpy/g

익명 사용자의 이미지

좋은 소재의 버그군여..

컴파일러 버그 같네염.. ^^

oprix_의 이미지

int
main( int argc, char *argv[])
{
int a=5;
int b=1;

float c=0.2;
float d;

d= (float)((float) b / (float)a);
printf( "in formula\n");
if ( (float)((float) b / (float)a) >= c) printf(" normal!\n");
else printf(" abnormal!\n");

printf( "in value\n");
if ( d >= c) printf(" normal!\n");
else printf(" abnormal!\n");
}

익명 사용자의 이미지

double c = 0.2 ;

컴파일러는 컴파일시에 분명히 투덜 댑니다. 버그가 아니죠.

oprix_의 이미지

제가 가진 gcc 2.96 에서는

$ gcc bug.c -Wall -o bug
bug.c: In function `main':
bug.c:11: warning: implicit declaration of function `printf'
bug.c:18: warning: control reaches end of non-void function

위의 경고만 얘기하네요..

익명 사용자의 이미지

D:\Test-Project\bug\bug.cpp(8) : warning C4305: 'initializing' : truncation from 'const double' to 'float'

흠.. 기본형인 double이 float으로 변형되면서 생기는 일 같은데 정확한 원인은 잘 모르겠군요..

Visual C++에서 입니다.

익명 사용자의 이미지

상수를 double 로 인식 하기 때문입니다.

=> float c=0.2f;

익명 사용자의 이미지

컴파일러쪽 버그같군여.. ^^

익명 사용자의 이미지

이건 잘 알려진 부동소숫점 문제인 듯 싶습니다.

#include

main()
{
int i;
double sum = 0.0;

for (i = 0; i < 10; i++)
sum = sum + 0.1;
if (sum == 1.0)
printf("ok!\n");
else
printf("no\n");
}

이 경우 no 가 찍힐겁니다.

부동 소숫점 수는 직접 비교보다는 크거나,작거나, 범위를 비교하시는게
안전합니다.

익명 사용자의 이미지

제일 멍청한(?) 버그 중 하나....

if(i=9)
printf("i 값은 9올시다 ");

스카리의 이미지

이런 실수는 코딩습관으로 고칠수있습니다.

if (9 = i)

라고 하시면 컴파일러가 떽떽 거리죠 -0-

익명 사용자의 이미지

하핫. 의도와는 다르지만 결과적으로는 i값은 9... ^^

ㅋㅋㅋ

liberta의 이미지

버그라기보단 컴파일러가 멍청해서 주인의 원래 의도를 눈치까지
못하는 예로, for 루프 쓰면서 이런 적이 왕왕 있었죠...

for (i=0; i /* 어쩌고 저쩌고... */
}

for도 동작 잘(?)하고, /* 어쩌고 저쩌고... */도 마찬가진데 -
원하는 동작은 안나오죠. 쩝... -_-a

이런 trivial mistake(뻔한 실수?)를 어떻게 컴파일러가 찾아주질
못할까요.... ;-)

Paladin의 이미지

이건 구문 오류가 아니죠. 그래서 컴파일러가 잡아 주지 않는거죠.

for (i=0; i {
/* 어쩌고 저쩌고... */
}

먼저나온 for문은 MAX만큼 아무 일도 하지 않은채 돌고나서 일을 끝내고,
그다음 { } 블럭으로 넘어가죠.
결과적으로 {/*어쩌고저쩌고*/}는 for문에 관계없이 많지도 적지도 않게 단 한번 실행하게 됩니다.

참고로 for, while,if문에 딸린 블럭외에도 그냥 아무 것도 조건 안달려도 블럭 지정이 가능합니다.

9th Paladin

익명 사용자의 이미지

ㅎㅎ
무한 루프를 만들때,
while(1);
이라고 해버리기도 하지만
for(;;);
라고도 왕왕 해버리거든요 :)

for (i=0; i /* 어쩌고 저쩌고... */
}

이런걸 뻔한 실수로 잡으면.... 틀림없이 컴파일러
안좋다고 투덜댈 사람 많을껄요 :)

dawnsea의 이미지

어떤 책으로 첨에 공부했는지 이런 것에서 티가 나드라구여.

저두 while(1) 보다 for(;;)를 많이 쓰는 편. ㅡ.ㅡ;

무슨 책에서 영향받았더라? ㅡ.ㅡ;;

vacancy의 이미지

이것도 제일 유명한 버그중 하나가 아닐까요

for ( i=0; i ..어쩌구..

while ( condition );
..어쩌구..

끝의 세미콜론요

익명 사용자의 이미지

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
저도 그런적이 있었읍니다..

if(조건문 한참~~~~~);
...
else
...

흘..왜 else 코드가 동작하는지.. 그 당시 if위 괄호안에 조건문이 길어서 끝에 있는
세미콜론을 보지를 못하였었죠.. 글구 이 버그도 내가 잡은것이 아니고 남이 지적해서
알게되었더랬읍니다..

liberta의 이미지

하하, 제가 "7초" 늦었군요.. ^^

익명 사용자의 이미지

#include
int main()
{
char *szName;
szName = "홍길동";
printf("당십의 이름은 %s입니다.\n", szName);
return 0;
}

// 이거 에러 아닌데요,.
// 메모리 할당할필요도없죠,.
// strcpy를 쓰는것도 아닐테고,.

int *ptr;
ptr=(int *)malloc(sizeof(int *)*3);

이건 sizeof(int *)라고 하지말고 sizeof(int)라고해야죠,
전적으로 사용자 실수입니다,.

익명 사용자의 이미지

아- 다시보니까, 조금 주제에 어긋나는 글을 올린것 같군요,.
죄송합니다.

godyang_의 이미지

사용자 실수가 그 프로그램에서 버그죠 ^^;

어짜피 이번 주제가 gcc의 버그를 찾는게 아니므로...(웬지 분위기가 gcc의 버그를 찾는 것 같은데...)

대부분의 버그가 사용자 과실로 발생하죠.

godyang_의 이미지

전 if문에 들어갔던 버그가 생각납니다.

OS Scheduling module에 대한 프로젝트로 C로 프로그래밍할 일이 있었는데...

if (temp=function(arg)!=0) {
...
}

여기서... function(arg)의 결과값이 0이랑 비교되는게 아니라 temp에 들어있던 원래값이 비교되더군요. -_-... 제 무지로 발생한 요놈의 버그를 몰라서 몇시간동안 삽질한 기억이 납니다.

Paladin의 이미지

연산자의 우선 순위는 외울게 조금있죠.

우선 순위가 같은 경우에만 순서대로 연산합니다.
그나마 그것도 왼쪽에서 시작하는 순서도 있고, 오른쪽에서 시작하는 순서도 있죠.

논리연산자와 할당 연산자는 머 별로 고민할 것도 없이 곰곰히 생각하면 논리연산자가 아무래도 우선 순위가 높을 거라고 당근 짐작할 수 있죠.

그리고 아래 경우에는 오른쪽에서 결합하는데, 가만 보면 "당근"입니다.
a=b=c=d=5;

왼쪽부터 결합하면 아무래도 어색하죠.

9th Paladin

익명 사용자의 이미지

그게 아니라요..

function(arg)와 0과 비교한다음

그게 참이면 temp에 1이

거짓이면 0이 들어갑니다.

godyang_의 이미지

그렇군요! 역시 무지했습니다 ㅡ.ㅠ 이제야 제대로 작동안하는 이유를 깨달았네요.

logout_의 이미지

일주일동안 헤메고 다녔던 버그입니다. 수치해석 프로그램이라서... 계산 결과만 보고 디버깅을 해야 하는데 그게 쉽나요. --;

for (j = i; j < k; j++)

이렇게 해야하는 것을

for (j = 1; j < k; j++)

이렇게 적었었습니다. 일주일 내도록 1을 i로 읽고 있었던 셈이죠. --;

Paladin의 이미지

무려 일주일!!!

솔직히 저도 저걸 착각한 경우가 단 한번 있었는데, 금새 찾아 냈죠.

본인의 경우에는 변수는 녹색, 숫자는 붉은 색으로 확연히 차이가 나도록 사용합니다.

이렇게 하면 졸라 복잡한 format 문자열을 구성할때도 그다지 헷갈리지 않죠.

색깔 구별은 SQL문 구성할때도 상당히 유용합니다.

9th Paladin

익명 사용자의 이미지

저도 이런적 많은데 :)
개발환경 폰트를 좀 구별하기 쉬운걸 쓰면 좀 낳을꺼에요,.

gilchris의 이미지

전 폰트 크기를 크게 해서 해결을 합니다.
폰트를 바꾸면 이상하게 적응이 안되서리... -.-;


--------------------------------------------------------------------------------
새로운 세상으로...

익명 사용자의 이미지

유명한 버그하나 ^__^

#include
int main()
{
char *szName;
szName = "홍길동";
printf("당십의 이름은 %s입니다.\n", szName);
return 0;
}

익명 사용자의 이미지

말씀하시는 사항은 분명이 맞습니다...

그러나 위의 코드에서는 문제가 안됩니다...
아래와 같이 사용할 때 말씀하시는 문제가 되는것이지요...

#include

char* print(void);

int main()
{
char *szName;
szName = printf();
printf("당십의 이름은 %s입니다.\n", szName);
}

char* print(void)
{ char *szName;
szName = "홍길동";

return szName;
}

익명 사용자의 이미지

이건 또 왜 버그죠?

이것역시 정상적인것인데요...

"홍길동"은 어차피 Data 영역에 있고 prinf::szName이 local variable일지라도

전달하는 값은 Data 영역입니다.

아무 문제 없네요... ㅡㅡ

익명 사용자의 이미지

아마 이걸 말씀하시려고 한게 아닐까요?

int funcA()
{
char *ptr ;

ptr = funcB();
printf("%s\n", ptr );
return 0;
}

char *funcB()
{
char *str = "홍길동";
char dest[100];

strcpy( dest, str );
return dest;
}

이부분은 당장은 실행은 가능하지만 잠재적으로 에러로 알고 있습니다. 뼈대만 써서 그런데 dest는 stack 영역에 메모리 할당된 부분이니까 return 되면서 stack이 해제되니까 다른 함수를 호출하다보면 엉뚱한 데이터들이 들어갈 것으로 사료됩니다.
틀리나요??

익명 사용자의 이미지

이게 왜 버그죠?
null pointer assignment를 말씀하시는 거라면... 아닌데요-,.-
제가 무식(혹은 무능력)해서 그런가요?

익명 사용자의 이미지

#include
int main()
{
char *szName;
szName = "홍길동";
printf("당십의 이름은 %s입니다.\n", szName);
return 0;
}

szName = "홍길동";
메모리를 allocation하지 않고 사용했기 때문에..
에러를 발생시킵니다.

shjeun의 이미지

포인터 부분 더 보셔야 하겠네요~ 그리고 constant는 이미 allocation되어 있어서~
write만 하지 않으면 됩니다. 예를 들어서

1: szName = "홍길동";
2: *szName = 'a';

이미 szName이 constant를 가리키고 있는 상황에서 "홍길동"의 내용을 바꾸려고 시도하는 것이므로 constant의 원칙에 어긋나죠~

:-)

익명 사용자의 이미지

그렇게 생각하시고 쓴것 같은데...
이 코드만으로는 아무런 문제도 없네요.
다만 이 후의 코드에서 szName 포인터에 대해서 어떤 조작을 하는 야에 달린 문제겠죠
이 코드까지의 진행으로는
홍길동은 BSS영역에 있는 것이고 코드가 로딩될때 같이 같이 로딩(공간을 확보하고)되겠죠.
그러니... szName은 BSS영역 어딘가를(정당한 포인터)를 가리키는 거죠.

vacancy의 이미지

제가 알기론 이건 문제가 없는걸로 아는데요.
만일 "홍길동"이라는 문자열을 strcpy로 szName에 카피해 넣었다면 버그죠.
그렇지만 이 경우는 "홍길동"이라는 문자열은 이미 메모리가 할당되어
실 메모리에 존재하게 됩니다. - 끝에 널문자열까지도 존재합니다.
szName = "홍길동"이라고 대입하는 순간 그 문자열의 번지가 szName에 들어가는거죠.
이후에 szName에 strcpy로 6바이트 이상의 문자를 복사해넣는다면 문제가 되겠지만
이 소스의 경우는 전혀 문제 없는걸로 알고 있습니다.
*szName이 아닌 szName의 값을 디버거로 보시면 확실할것같네요.

익명 사용자의 이미지

szName 를 고치는 어떤 시도도 Segmentation fault 를 발생시킵니다.
szName 이 "홍길동" 을 가리키는 것은 정당한 것이지만,
이 "홍길동" 이 있는 위치는 코드영역, 즉 내용을 고칠수는 없는 부분입니다.
(Dos 는 제외합니다 ^^;;)

익명 사용자의 이미지

좀 원론적인 얘기를 하자면, C언어 표준 자체에서는 코드 영역과 데이터 영역을 구분하지 않습니다. 다만 '문자열 상수를 바꾸려고 할때, 그 행동은 정의되지 않았다"라고 쓰여있을 뿐입니다.

C99 Final draft N869, 6.4.5.6
If the program attempts to modify such an array, the behavior is undefined.

vacancy의 이미지

"홍길동"의 위치는 코드영역이 아닌걸로 알고있고요.
실제 소스에서 내용을 고치지도 않습니다.
혹시나 해서 컴파일해봤는데 문제 없군요.
또 szName을 고치는 시도가 seg-fault를 발생시킨다는것도 이해가 안가네요.
szName은 main내의 char*형 변수일 뿐입니다.
szName이 가리키는 곳이 읽기/쓰기에 문제가 있는 곳인 경우에
*szName에 접근하는 것이 seg-fault를 발생시킬수는 있겠죠.
'='로 대입하는 것과 strcpy로 대입하는 것은 아주 다른 명령입니다.

익명 사용자의 이미지

앗...제가 잘못 썼군요...^^;;;
szName 을 고치는게 아니라 *szName 입니다 ^^;;;

익명 사용자의 이미지

변수는 데이터영역에 저장되지만 상수와 문자열은 코드영역입니다.

int a;

이것은 zerovars 섹션에 들어갑니다. (데이터영역)

int a = 4;

a라는 변수가 언제든 바꿀 수 있으므로 초기화된 변수, 즉 vars 섹션에 들어갑니다.

const int a = 4;

이것은 바뀌지 않는 값이므로 const 섹션에 들어갑니다. (코드섹션타입입니다.)

char *a = "ABCD"

이것은 strings 섹션에 들어갑니다. (코드섹션타입입니다.)

컴파일러 매뉴얼 찾아봤습니다...
그럼 이만.

익명 사용자의 이미지

말씀하신 zerovars, vars, const, strings 섹션은 *그* 컴파일러에서 사용하는것 용어인 듯 싶습니다. ^^
어셈블리 코드를 생성한 경우에도 그런 이름으로 구분해서 사용할 수도 있는 것 같다는 생각이 들기도 합니다. 제 생각으로는 어셈블리 코드 생성시 일정한 영역을 그 성격에 따라 나누어서 컴파일러에서 임의로 명명한 것이고, 실제에 있어서는 몇개가 합해지지 않을까 생각되는데요, 또 모르죠. 위의 말씀하신 개념이 어쩌면 링커나 로더도 그런 구조를 쓸 수도 있겠지요.

뭐 용어야 CPU나 컴파일러, 로더 계열에 따라서 좀 틀리게 쓰겠지만서도,
메모리 영역을 크게 네개로만 생각해 봅시다.
코드, 데이터, 스택, 힙으로요.

그리고 char *a = "ABCD"; 는 함수 (main을 포함) 안에서 정의된 것이라고 하고요.

그렇담 제 생각은 a 는 스택에, "ABCD"는 데이터에, "ABCD"의 (주소)값 (포인터상수라고 하나요?)은 코드에 들어있다고 생각합니다.

const int a = 4;

는 컴파일러 구현에 따라 여러가지 처리 방식이 있을 수 있을 듯 합니다. 타입검사만 컴파일시에 하고, 실제로는 4라는 값을 코드에 박아버리는 수도 있겠고, 아니면 read-only로 되어 있는 데이터영역에 두고 참조할 수도 있겠지요. 옵션이나 구현에 따라서는 read-only 속성이 없을 수도 있겠고요.

그러나 많은 경우에

char *a = "ABCD" 는
위에 말씀드린 대로 구현할 것으로 생각됩니다.
"ABCD"의 주소값은 (좁은 의미의)코드의 일부분이겠지만,
"ABCD"값은 데이터이기 때문에 데이터영역에 있는 것이 자연스러워보입니다.

어떤 아키텍쳐에서 어떤 OS에, 어떤 컴파일러를 사용하시나요?
유닉스 계열은 아닐듯 한데요.
논의의 정확성을 기하기 위해 혹시 컴파일러 메뉴얼의
해당 부분과 생성된 어셈블리 코드를 올려주실 수 있으신지요?

익명 사용자의 이미지

컴파일이나 실행시에는 아무런 문제가 없는데요 ?

익명 사용자의 이미지

숫자 초기화나 문자열 초기화 모두 프로그램 로딩시 일어납니다. (제가 알기로 ) 즉 프로그래밍 로딩 되면서 숫자 데이터면 숫자가 변수에 문자열은 문자열이 저장된 주소가 포인터에 할당됩니다.

int a = 0;

프로그램이 로딩될 때 또는 함수가 호출될 때 0이란 숫자가 할당됩니다.
static 이 선언된 경우에는 프로그램이 초기화 될 때 할당됩니다.
문자열의 경우 지금 이슈가 되는 것 처럼

char *ptr = "홍길동"; 이라고 하면 실제 "홍길동"이란 데이터는 데이터 영역에 잡혀있고 ptr 은 그 주소 ( 포인터가 주소 아닙니까 )를 가르키고만 있읍니다. 아마 (char*) ptr + 8은 전혀 엉뚱한 데이터를 가르키겠지요.

char *ptr = "홍길동"; 이라고 한것은 전혀 문제가 되지 않습니다.
다만 strcpy( ptr, "홍길동" ) ; 하면 문제를 일으키겠지요. 이때는 ptr은 전혀 초기화 되지 않은 포인터이므로 데이터를 복사할 수 없죠.
역시 포인터는 이해하기 힘들고 항상 헷갈리고 주저하게 만드는 주제군요.. ^^
저는 확실하게 하기 위해 특별한 경우 아니면 항상 char aaa[SIZE]로 할당해서 쓰고 포인터를 써야하는 특별한 경우 ( 예를들어 토큰을 분리하거나 문자열을 일부 조작하기 위해서 같은 경우 )에만 씁니다. 또는 다차원 배열같은걸 할때 배열속을 헤집고 돌아다니기 편하려고만 쓰죠..

익명 사용자의 이미지

문제가 없을수"도" 있습니다만...

할당되지 않은 영역의 메모리를 사용했기 때문에,

임으로 지워지거나 할 수도 있고,

쓰려는 곳의 메모리가 접근 불가능할 경우

segmentation fault 오류가 날 수도 있습니다.

익명 사용자의 이미지

제가 알기로는 오류가 안나는것으로 알고 있습니다.

char * a = "abc";

이런식으로 하면 "abc"는 메모리가 따로 할당되는것이 아니고 프로그램의 실행 코드 안에 그냥 박혀 있다가 포인터인 a가 그 주소를 저장하는것으로 알고 있습니다.

그러니까 strcpy( a, "abcd"); 이런식으로만 사용하지 않는다면 아무 문제 없는것으로 알고 있습니다.

그리고 그런 비슷한 방법으로 사용했을때 이상해지는것은 아래와 같은 경우겠지요.

int * f()
{
int result;
result = 어쩌고저쩌고;
return &result;
}

익명 사용자의 이미지

무슨 문제가 있을지 알 수 없다, 가 문제입니다. :) 럭비공이죠.
--
from [ke'izi] : where is [r]?

익명 사용자의 이미지

아닙니다. 문제 없습니다가 정상입니다. 이 예제

char *str;
str = "This";

이건 아무런 문제가 없습니다. 만일 이 코드에 놓고 무슨 문제가 있을지 알 수가 없다라는 식이라면

printf("TEST");

이 코드도 알 수 없다가 되어야 합니다.

원래코드를 의미해 보면 char를 가리키는 포인터를 정의해 놓은 다음에 "This"라는 문자열 포인터 상수(주소)를 뽑아 내 주면 그값을 str이라는 포인터에 넣어 놓는 극히 정상의 코드입니다. ""로 묶은 것은 문자열 상수 포인터를 만들라는 이야기 이고 이건 여러분들이 사용하는 그 수많은 문자열 상수입니다.

위에 어떤 분이 말씀하신 것처럼 이 상황에서

strcpy(str, "THIS");

이코드는 문제가 있으나 위의 코드는 지극히 정상입니다.

익명 사용자의 이미지

버그라기보단 제 무지 때문에 일어난 해프닝이지만
리틀/빅 엔디안 때문에 구조체를 거꾸로 만들어야 했던 게 있죠.
조합형 한글을 유니온과 구조체에 넣으면 깔끔하게 첫가끝이 분리되는데
이때 유니온과 구조체의 구조가 머릿속에 그리는 것처럼 0부터 시작하는 게 아니었습니다.
코드를 이것저것 넣어가면서 뭐가 잘못된 건지 대조해보고
하이텔 리동에 질문까지 올리고 나서야 겨우 수습이 됐죠 :)
요즘 마침 리틀/빅 엔디안이 제 눈에 자주 띄어서 생각나네요..
--
from [ke'izi] : where is [r]?

익명 사용자의 이미지

그런 이유로 많은 경우에 공용체(union)보다는 비트연산자를 사용하는 것이 권장됩니다.

lovehis의 이미지

저역시 VC로 한글 오토마타 잡업하다가 똑같은 문제로.... 하룻밤 머리를...

--
늘...

익명 사용자의 이미지

int *ptr;
ptr=(int *)malloc(sizeof(int *)*3);

제가 자료구조 공부를 할때쯤 이런식의 실수를 한 적이 있습니다.
터보씨로 숙제를 하고 있었는데 결과값이 실행을 할때마다 다르게 나오더군요..첨에는 '혹시 컴파일러 버그가 아닐까'라는 생각에 다른 친구한테 보내서 VC++로 컴파일을 했는데 정상적으로 작동했습니다. 근데 결국 그 친구가 이 실수를 찾아주더군요...(이 일로 VC++을 볼때는 항상 삐딱한 시선으로..)

익명 사용자의 이미지

이런경우는

int* ptr = new int[3];

이렇게 하는것이 여러모로 좋지 않을까요.

구지 malloc을 사용하고 싶다면

int* ptr = (int*)malloc( sizeof( int[3] ) );

sizeof() 는 인수안의 것을 평가하기 위해서 실제 메모리 할당 같은것은 안합니다.
그러니까 sizeof(int[10000000000]) 이렇게 해도 전혀 이상이 없습니다.
오히려 구조체의 pack, n byte align 으로 생기는 문제로부터 보호될 수 있을것입니다.

익명 사용자의 이미지

VC++이 제대로 해주었는데 왜 삐딱한 시선으로?
16비트 컴파일러 써서 삽질하신거 아니에요?

익명 사용자의 이미지

VC++의 죄는 아닌 듯...^^;

int*나 int나 윈도에서는 크기가 4니까...그랬겠져...

그리고 16비트 컴파일러를 써서 삽질했다기 보다는...

자기 잘못이져...

익명 사용자의 이미지

사족이지만 외국 프로그램을 보다 보니까 이식성을 생각해서 모든 데이터 타입을 재정의해서 쓰더군요. 아주 단순 무식하달 정도로..
예를 들어서
typedef int char[2];
typedef long char[4];
이런식으로요.
아마 디자인이 예전에 되서 16비트 기준으로 되었던것 같은데 처음 디자인한사람이 엄청난 고민을 했던것 같더군요. 덕분에 이 프로그램은 몇몇 플랫폼(Mainframe급)을 제외하고는 OS 영향을 받지 않더군요. 단, MS 윈도우에는 포팅못한다고 하더라구요. ㅠㅠ.

김용욱_의 이미지

잠시 테스트 해봤습니다.

#include

main()
{
typedef int char[4];
int a;

a=35555;

printf("%d",a);

a++;

printf("%d",a);
}

에러가 나는군요.
a.c: In function `main':
a.c:5: parse error before `['

흠;; 피곤해서 다시 안살펴봤는데 제가 잘못한게 있습니까?
--
L.I.T

L.I.T

익명 사용자의 이미지

a.c 를 a.cpp로 고치고 컴파일해 봤나요?

typedef int char[4]; 가
C에서는 에러라고 알고있는데...
적어도 C++에서는 합법입니다.

비슷한 걸루 cast 연산자가 있는데요...
C에서는 (type)(어쩌구저쩌구) 만 합법이지만
C++에서는 type(어쩌구저쩌구) 도 가능하니까요

익명 사용자의 이미지

절대 아니죠.
(typedef) int char[4]; 와 같은 선언은 C에서도 C++에서도 부적법합니다.

왜냐? char는 예약어니까.

그리고 char[4]를 INT라는 이름으로 정의하려면
typedef INT char[4];가 아니고 typedef char INT[4];입니다.
순서가 거꾸로네요.

김용욱_의 이미지

같은 소스에 대한 c++ abc.cpp의 결과입니다.

[c20112034@lxcit c20112034]$ c++ abc.cpp
abc.cpp: In function `int main ()':
abc.cpp:5: parse error before `['

파일명만 abc.cpp로 바꾸었습니다.
실력이 없어서 무엇이 문제인지는 모르겠습니다.
--
L.I.T

L.I.T

cppig1995의 이미지

생각을 해보세요.
typedef 안쓰고, 그냥 모든 int를 char[2]로 쓴다고 합시다.
char a[2] = 32126; 하면 대입이 될것같나요?

그리고 어떤 컴파일러가 위의 대입을 지원하는 확장이 있다고 해도,
이러한 방법으로 signed int를 구현할 순 없습니다.
char 두 개를 붙이면 -16384부터 16383까지 표현할 수 있겠고,
unsigned char 두개면 unsigned int와 같겠죠.
char+unsigned char면 그건 배열이 아니죠.

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

익명사용자의 이미지

초년시절에는 컴파일러와 lib가 잘못됐다.... 띠불띠불....
말년시절에는 내가 또 뭘 잘못짰나.... ㅜㅜ....

페이지