[질문] C 언어 고전적인 함수 정의 형식에 대한 지원

체스맨의 이미지

라이브러리 하나를 공개 프로젝트화 할 생각이 있습니다. 별 대단한 건 아닌데, 96년부터 학교일, 회사일 등등에 쓰여왔던 것들 중 일부로, 기능에 비해 개발 기간은 무지 깁니다. -_-; 좀 더 기능상으로 추가하고 공개하고 싶었지만, 공개가 먼저되는게 한 두 분이라도 좀 써 주시고 하면 재밌게 개발 할 수 있지 않을까 해서요. ( 쓰다보니 글이 좀 길어지는군요. )

라이브러리 성격으로 보자면, glib 과 공통점이 있다고 볼 수 있구요. 개발 시작일로 따지면 제가 먼저인가요? ^^;

뭐 아무튼 그런 상태인데, 소스 올리기 전 몇개 짚고 넘어가고 싶은 게 있는데 그 중 하나가 C 의 고전적인 함수 정의 형식 지원에 관한 것입니다.

다음과 같은 고전적 형식과

int
function( a, b, c )
char a;
int b;
double c;
{
        ...
}

다음과 같은 현대적 형식을

int
function( char a, int b, double c )
{
        ...
}

동시에 지원하고 싶은 것입니다.

X11 라이브러리 소스를 보면 다음과 유사하게 되어있더군요. 매크로 이름이 뭐였는지는 정확히 기억이 안나네요. 대충 CLASSICAL_DEFINITION 라고 합시다.

int
function
#ifdef CLASSICAL_DEFINITION
  char a;
  int b;
  double c;
#else
  ( char a, int b, double c )
#endif
{
        ...
}

제 생각에 이런식은 좀 지저분했습니다.
질문 1. X 라이브러리 스타일에 대해, 어떻게 생각하시는지요? 가독성은 어떻습니까?

그래서, 나름대로 새로운 매크로를 정의해봤습니다.

#if defined(__MODERNPARAM__) || defined(__cplusplus)
#       define P_A(param) param
#       define P_B(param) (
#       define P_E )
#       define P_X ,...)
#       define P_N ,
#       define P_V ( void )
#else
#       define P_A(param) ()
#       define P_B(param) param
#       define P_E ;
#       define P_X ; va_dcl
#       define P_N ;
#       define P_V ()
#endif /* defined(__MODERNPARAM__) || defined(__cplusplus) */

#define P_1
#define PARAM_API   P_A
#define PARAM_BEGIN P_B
#define PARAM_END   P_E
#define PARAM_VAR   P_X
#define PARAM_AND   P_N
#define PARAM_VOID  P_V
#define PARAM_1ST   P_1

이렇게 하면 위 함수는

int
function
P_B(( a, b, c ))
P_1  char a
P_N  int b
P_N  double c
P_E
{
        ...
}

이렇게 됩니다. 과거에는 회사에서 작성하는 코드에도 좀 해봤습니다만 부정적인 견해를 들었습니다. 사실 윈도용 코드만 만들면 되는 회사에서 이런 일은 애초에 쓸데없는 생각이었죠.

질문 2. 제가 해본 방식은 어떻습니까?

일단, 저는 고전적 스타일을 지원하고는 싶습니다. 그래서 지금 방법이 괜찮은지 아니면 어떤 다른 방법이 있을 지 말씀해주시는 게 더 좋겠구요. 그리고 더 궁금한 것은 질문1 및 2 에서 제시한 코드가 어떤 느낌이 드는지입니다. 그냥 C 언어로서 가독성의 범위를 크게 벗어나지 않고 봐줄만하다던가, 그게 뭐냐라던가 뭐 그런거요. 어쨌든, X 라이브러리처럼, 그것을 지원하는 경우도 있다는 점을 고려해주시고, 저는 견해를 좀 들어본 뒤 최악의 경우는 아예 저런 코드를 제거해버릴지도 고민해볼 생각입니다.

체스맨의 이미지

-_- 답글이 하나도 없군요.
너무 관심 외의 질문이었던 것 같습니다. :oops:

Orion Project : http://orionids.org

mach의 이미지

저는 견해가 다릅니다.
10여년전이라면 필요할듯하지만, 이 부분에 대한 제 견해는, 소스수준에서
호환을 맞추는것보다는 이젠 컴파일러(89이후)에게 맡기는게 타당한듯합니다.
대부분의 시스템에서

Quote:
'현대적 형식'
을 지원하는 컴파일러를
제공하는 현재에는 별로 무의미해 보입니다.
단지, 매크로를 사용한 효과로 코드를 볼때, 보다 readability가 나아진다면,
좋은 코딩 스타일로 여길 수 있을것도 같습니다. 그러나, 이러한 코딩스타일 또한
전체 프로젝트 구성원이 받아들여야 제 구실을 할 수 있지 않을까합니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

pinetr2e의 이미지

체스맨 wrote:

일단, 저는 고전적 스타일을 지원하고는 싶습니다.

왜 고전적인 방법을 지원하고 싶으신지 궁금하군요 ?
어떤 특별한 이유가 있으신지요?
아니면 단지 예전 방식만을 처리하는 컴파일러에 대한 고려를 위해서 그러는 것인지 ?

crimsoncream의 이미지

C ARM에 나와 있는 예제인데
declaration은 선택적으로 하도록 하고 definition은 traditional로 할 것을 권합니다. 글의 문맥을 살표볼때는 traditional 방식도 표준에서 지원하도록 돼 있는 것 같습니다. 그리고 gnu 코딩 컨벤션에서도 traditional 방식을 권하고 있습니다. 리누스야 이걸 못 마땅하게 생각하고 있는 거 같지만 :)

#ifdef __STDC__
#define PARMS(x) x
#else
#define PARMS(x) ()
#endif

extern int f PARMS ((int a, double b, long c));

int
f (a, b, c)
     int a;
     double b;
     long c;
{
  return a + b + c;
}

어, 근데 다시 보니까 c++ 컴파일러의 사용도 고려하고 계신것 같군요.
그러면 traditional로 안되겠군요. 개인적인 생각으로는 c code는 c 컴파일러로 작업하는게 더 좋을 것 같은데요 :)

오늘 우리는 동지를 땅에 묻었습니다. 그러나 땅은 이제 우리들의 것입니다.
아직도 우리의 적은 강합니다. 그러나 우리는 그들보다 많습니다.
항상 많을 것입니다.

체스맨의 이미지

예전에 좀 오래된 HP-UX 에서 그 라이브러리를 빌드할 기회가 있었는데요. 옵션을 주지 않은 기본 상태에서는 고전적인 함수 정의 형식이 기본이더군요. 그게 계기가 됐습니다. 컴파일러 옵션에 의존적이지 않게 최악의 경우에도 'C 컴파일러라면' 빌드될 수 있도록 하는 것이 하나의 목표이기도 했거든요.

게다가, 말씀 드렸던 것처럼, GLib 과 공통되는 부분이 있고, 특히 플렛폼 호환성에 대한 고려가 되어 있는 라이브러리입니다. 위와 같은 일례도 그런 고려 중의 하나였구요.

mach wrote:
이러한 코딩스타일 또한 전체 프로젝트 구성원이 받아들여야 제 구실을 할 수 있지 않을까합니다.

이것이 저도 가장 걸리는 부분입니다.

다만, crimsoncream님께서 예시하신

extern int f PARMS ((int a, double b, long c)); 

또는 예를 들면, zlib 처럼

ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));

등과 같이, 플렛폼 호환성을 위해 앞 뒤에 현란하게 붙는 수식어들은 다른 플렛폼 호환성을 염두에 두는 라이브러리들이 헤더에서 그러한 형식으로 함수 프로토타입을 기술하고 있긴 합니다.

한편으론 언급했듯이, X 라이브러리와 같은 큰 프로젝트에서도 두가지 형식을 별도로 지원하고 있기도 했구요.

crimsoncream 님 말씀처럼, 고전적인 방식을 권장하는 곳이 있긴 하지만, 또 막상 그 쪽으로만 가자니 뭔가 꺼림칙해서 양다리를 걸쳐보자는 생각이었습니다. 가장 큰 우려는 독단적인 코딩 스타일로 비추어질 수 있다는 것이지요. 실제로 거부감을 갖는 사람을 봤습니다. 그 분 또한 제가 만든 헤더를 열고 이해해보려는 노력이 없는 것 같아 아쉽기도 했지만요.

Orion Project : http://orionids.org

체스맨의 이미지

헤더에는 화려한 수식어를 어쩔 수 없이 붙인다해도, 소스에서는 고전적인 형식을 취하기로 결심 했습니다. crimsoncream 님 말씀대로요. 그게 제가 원하는 방향에서 코드 모양을 해치지 않는 가장 합리적인 방법 같네요.

미래에도 C 에서는 고전적인 형식 지원이 중단되지는 않으리라 생각되구요.

Orion Project : http://orionids.org

lsj0713의 이미지

C99 6.11 Future language directions 에는 다음과 같은 내용이 있습니다.

Quote:

6.11.6 Function declarators

1 The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.

6.11.7 Function definitions

1 The use of function definitions with separate parameter identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.

따라서 C99 이후의 표준에서는 언제든지 전통적인 함수 선언과 정의 방식이 사라질 수 있습니다.

게다가 원형 정의와 비원형 정의를 섞어쓰는 것은 매개변수 데이터형에 대해서 골치아픈 문제를 유발할 수 있습니다.

우선 원형으로 정의된 함수가 비원형 선언과 호환되기 위해서는 다음의 규칙을 만족해야 합니다. (C언어 펀더멘탈 p.552)

Quote:

호환되는 반환형을 가져야 한다.
원형으로 정의된 함수가 가변인자를 받는 함수가 아니어야 한다.
원형으로 정의된 함수의 각 매개변수에 기본 인자 진급을 적용한 결과가 적용하기 전의 데이터형과 호환되어야 한다.

반대로, 비원형 정의와 원형 선언이 호환되기 위해서는 다음의 규칙을 만족해야 합니다.

Quote:

호환되는 반환형을 가져야 한다.
매개변수의 개수가 같아야 한다.
비원형 정의의 매개변수에 기본 인자 진급을 적용한 결과로 나오는 데이터형은 원형 선언의 매개변수 데이터형과 호환되어야 한다.

이 두가지 경우에서는 모두 매개변수에 기본 인자 진급이라는 과정을 거치게 됩니다.

Quote:

If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions

따라서 다음과 같은 코드들은 모두 잘못된 코드들입니다.

/* C언어 펀더멘탈 p.553 */
int func2();

int func2(short int a, float b, int *c) { /* ... */ }
/* short int a는 기본 인자 진급 과정을 거치면 int a가 되며, 적용되기 전의 데이터형과 호환되지 않는다. */

/* C언어 펀더멘탈 p.554 */
int func(a, b, c, d)
int a;
short int a, b[];
float d;
{
}

int func(short int a, short int b[], int c, double d);
/* int a에 기본 인자 진급 과정을 적용한 결과인 int a가 원형 선언에 나온 short int a와 호환되지 않는다. */

비원형 선언과 비원형 정의를 조합하는 경우에는 단지 호환되는 반환형만 가지면 되지만, 이 경우에는 비원형 선언을 사용할 때 가지는 문제점들을 모두 가지게 됩니다. 매개변수의 갯수와 타입을 검사하지 않지요.

위와 같은 점들을 고려해 볼 때, 일괄적으로 비원형 정의(전통적인 함수 선언 방식)을 사용하는 것은 여러가지로 불편해 보입니다.

제 생각에는 그냥 원형 선언과 정의를 사용하시고, 비원형 선언과 정의를 사용해야 되는 상황에 마주쳤을 때에만 #ifdef ... #endif 를 추가하는 것이 더 나은 해결책 같습니다(아니면 해당 컴파일러 버젼을 따로 만들던가;;). 원형 선언과 정의를 지원하지 않는 C 컴파일러는 이제 드물지 않습니까? 아무리 매크로를 사용한다고 해도 일일이 선언마다 코드를 추가하는 것 보다는 Makefile에서 컴파일러의 옵션을 다르게 지정해주는 쪽이 더 노가다를 줄일 수 있다 생각됩니다.

ps. 물론 이건 원론적인 얘기일 뿐이고 '무조건' 원형 선언과 정의를 지원하지 않는 C 컴파일러를 사용해야 되는 상황이라면 어쩔 수 없겠지요.

체스맨의 이미지

lsj0713 wrote:

따라서 C99 이후의 표준에서는 언제든지 전통적인 함수 선언과 정의 방식이 사라질 수 있습니다.

구식이라고 돼 있는 것은 당연한 일이지만, 거기에 없애겠다고 써있진 않습니다.

고전적인 형식을 사용하기로 결심하기 전 여러 라이브러리나 응용프로그램들을 검토해봤구요. 유닉스 계열의 많은 유명한 프로그램들이 전통적인 함수 정의 방식을 사용하고 있었습니다. 그러므로, 없앨 가능성은 거의 없다고 봅니다.

lsj0713 wrote:

게다가 원형 정의와 비원형 정의를 섞어쓰는 것은 매개변수 데이터형에 대해서 골치아픈 문제를 유발할 수 있습니다.

익히 알고 있는 바입니다만, 제대로 사용하면(섞어쓰지 않으면) 문제가 없습니다. 예로 드신 함수에 대해

#ifdef PROTO
#    define __PARAM(p) p
#else
#    define __PARAM(p) ()
#endif

int func2 __PARAM(( short int a, float b, int* c ));

int
func2( a, b, c )
	short int a;
	float b;
	int* c;
{
	printf( "%d %f %d\n", a, b, *c );
	return 0;
}

만일 PROTO 가 정의돼 있는 상황이라면, func2 는 현대적 형식을 사용한 것과 동일하게 정의되고, PROTO 가 정의돼 있지 않다면, C 컴파일러가 promotion 을 적용해서, int func2( int a, double b, int* c ) 와 같이 컴파일 합니다.

두 형식을 섞어쓰지 않을 것이기 때문에, 두가지 형식을 모두 취하려면 고전적 형식을 사용하는 게 대안이라는 결론이었구요. 제가 정의한 매크로는 아무래도 소스 코드 가독성에 일부 거부감을 미친다는 것을 인정했지요.

Orion Project : http://orionids.org

전웅의 이미지

체스맨 wrote:
lsj0713 wrote:

따라서 C99 이후의 표준에서는 언제든지 전통적인 함수 선언과 정의 방식이 사라질 수 있습니다.

구식이라고 돼 있는 것은 당연한 일이지만, 거기에 없애겠다고 써있진 않습니다.

"구식 기술"로 표시해 둔 이유가 프로그래머에게 사용을 억제 시켜 추후
손쉽게 제거하기 위함입니다. 즉, 예전 C99 세미나에서도 언급한 적이
있지만, "구식 기술(obsolescent feature)" 이라는 용어가 단지 "구식인
기술" 을 의미하는 것은 아닙니다. 보다 공식적인 의미를 갖습니다.

체스맨 wrote:
고전적인 형식을 사용하기로 결심하기 전 여러 라이브러리나 응용프로그램들을 검토해봤구요. 유닉스 계열의 많은 유명한 프로그램들이 전통적인 함수 정의 방식을 사용하고 있었습니다. 그러므로, 없앨 가능성은 거의 없다고 봅니다.

덕분에 "구식 기술" 로 지정하고 10년이 지나도 없애지 못하고 있습니다.
C99에서도 살아 남았으므로 앞으로 최소 5년 정도는 더 버틸 것 같습니다.
ANSI C 라는 이름으로 표준이 발표된지 거의 15년이 지났습니다. 대체
얼마나 대단한 환경들이 현대 프로그래밍 언어가 다 쓰는 함수 원형을
제공하지 않기에 "지금" 개발되는 프로그램들이 구식 선언을 고려해야 하는
것인지 궁금합니다. 과거에 제작된 프로그램의 경우 유지보수 문제로
유지되고 있다지만 새로 개발되는 프로그램이 K&R C 를 고려할 이유가
있는지 심히 의심스럽습니다. 제 책에서도 이 논의에서 언급되었던 기법을
소개하고 있지만, 이는 사용을 장려하기 위함이 아니라 다른 곳에서 사용된
경우 이해를 돕기 위해서 다루고 있는 것 뿐입니다.

체스맨 wrote:
lsj0713 wrote:

게다가 원형 정의와 비원형 정의를 섞어쓰는 것은 매개변수 데이터형에 대해서 골치아픈 문제를 유발할 수 있습니다.

익히 알고 있는 바입니다만, 제대로 사용하면(섞어쓰지 않으면) 문제가 없습니다. 예로 드신 함수에 대해

#ifdef PROTO
#    define __PARAM(p) p
#else
#    define __PARAM(p) ()
#endif

int func2 __PARAM(( short int a, float b, int* c ));

int
func2( a, b, c )
	short int a;
	float b;
	int* c;
{
	printf( "%d %f %d\n", a, b, *c );
	return 0;
}

만일 PROTO 가 정의돼 있는 상황이라면, func2 는 현대적 형식을 사용한 것과 동일하게 정의되고, PROTO 가 정의돼 있지 않다면, C 컴파일러가 promotion 을 적용해서, int func2( int a, double b, int* c ) 와 같이 컴파일 합니다.

lsj0713 님은 그게 아니라고 설명하고 있는 것입니다. 내용을 다시 확인해
보시기 바랍니다. 이미 오해하고 계신 것처럼 원형/비원형을 함께 사용하기
위해서는 매개변수 데이터형에 더 신경을 쓰셔야 합니다.

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

lsj0713의 이미지

체스맨 wrote:

#ifdef PROTO
#    define __PARAM(p) p
#else
#    define __PARAM(p) ()
#endif

int func2 __PARAM(( short int a, float b, int* c ));

int
func2( a, b, c )
	short int a;
	float b;
	int* c;
{
	printf( "%d %f %d\n", a, b, *c );
	return 0;
}

만일 PROTO 가 정의돼 있는 상황이라면, func2 는 현대적 형식을 사용한 것과 동일하게 정의되고, PROTO 가 정의돼 있지 않다면, C 컴파일러가 promotion 을 적용해서, int func2( int a, double b, int* c ) 와 같이 컴파일 합니다.

FreeBSD + gcc 2.95.4 에서 위의 코드를 직접 해본 결과, 흥미롭게도 함수 원형을 int func2(short int a, float b, int* c); 로 하던 int func2(int a, double b, int* c);로 하던 아무런 문제가 없었습니다. (Visual C++에서도 해보면 좋겠지만... 집이 아니라서 당장은 어떻게 할수가 없습니다;;;)

이것이 원래 그렇게 해도 아무런 문제가 없는 것인지(이건 문서 찾아보면 나오겠지만, 지금은 옆에 문서도 없고 밤도 늦었으므로...;;;), 아니면 gcc 에서만 그렇게 동작하는 것인지(gcc의 설계 방식에 의한 의도하지 않은 특성인지 아니면 프로그래머의 실수를 방지하기 위해서 덧붙인 의도적인 특성인지)는 잘 모르겠습니다.

그러나 뉴스그룹에서는 대체로 원형 선언과 비원형 정의를 섞어쓸 때에는 int func2(int a, double b, int* c); 쪽을 사용하라고 권하고 있더군요.

http://groups.google.com/groups?selm=1991Feb28.072947.28885%40athena.mit.edu
http://groups.google.com/groups?selm=8dfpji%24krc%241%40elf.bsdi.com

권하는 이유가 단지 표준에 그렇게 적혀 있기 때문인 것인지, 실제로 문제가 발생한 사례가 있어서 그런 것인지까지는 잘 모르겠습니다.

어쨌든, 위의 글에서의 충고를 따른다면 원형 선언과 비원형 정의를 섞어 쓸때는 매개변수 타입을 좀 더 신경써서 결정해야 합니다. 그래서 저는 원형 선언과 원형 정의를 그냥 사용하기를 권했던 겁니다. 하지만, 지금의 저로서는 문제가 발생하는 구체적인 사례를 들 수 없으므로 더 이상 강하게 권하지는 않겠습니다.

부족하거나 틀린 내용이 있다면 실력있는 다른 분들이 첨언해 주실 거라 믿습니다. :-)

전웅의 이미지

lsj0713 wrote:
체스맨 wrote:

#ifdef PROTO
#    define __PARAM(p) p
#else
#    define __PARAM(p) ()
#endif

int func2 __PARAM(( short int a, float b, int* c ));

int
func2( a, b, c )
	short int a;
	float b;
	int* c;
{
	printf( "%d %f %d\n", a, b, *c );
	return 0;
}

만일 PROTO 가 정의돼 있는 상황이라면, func2 는 현대적 형식을 사용한 것과 동일하게 정의되고, PROTO 가 정의돼 있지 않다면, C 컴파일러가 promotion 을 적용해서, int func2( int a, double b, int* c ) 와 같이 컴파일 합니다.

FreeBSD + gcc 2.95.4 에서 위의 코드를 직접 해본 결과, 흥미롭게도 함수 원형을 int func2(short int a, float b, int* c); 로 하던 int func2(int a, double b, int* c);로 하던 아무런 문제가 없었습니다. (Visual C++에서도 해보면 좋겠지만... 집이 아니라서 당장은 어떻게 할수가 없습니다;;;)

이것이 원래 그렇게 해도 아무런 문제가 없는 것인지(이건 문서 찾아보면 나오겠지만, 지금은 옆에 문서도 없고 밤도 늦었으므로...;;;), 아니면 gcc 에서만 그렇게 동작하는 것인지(gcc의 설계 방식에 의한 의도하지 않은 특성인지 아니면 프로그래머의 실수를 방지하기 위해서 덧붙인 의도적인 특성인지)는 잘 모르겠습니다.

그러나 뉴스그룹에서는 대체로 원형 선언과 비원형 정의를 섞어쓸 때에는 int func2(int a, double b, int* c); 쪽을 사용하라고 권하고 있더군요.

http://groups.google.com/groups?selm=1991Feb28.072947.28885%40athena.mit.edu
http://groups.google.com/groups?selm=8dfpji%24krc%241%40elf.bsdi.com

권하는 이유가 단지 표준에 그렇게 적혀 있기 때문인 것인지, 실제로 문제가 발생한 사례가 있어서 그런 것인지까지는 잘 모르겠습니다.

어쨌든, 위의 글에서의 충고를 따른다면 원형 선언과 비원형 정의를 섞어 쓸때는 매개변수 타입을 좀 더 신경써서 결정해야 합니다. 그래서 저는 원형 선언과 원형 정의를 그냥 사용하기를 권했던 겁니다. 하지만, 지금의 저로서는 문제가 발생하는 구체적인 사례를 들 수 없으므로 더 이상 강하게 권하지는 않겠습니다.

부족하거나 틀린 내용이 있다면 실력있는 다른 분들이 첨언해 주실 거라 믿습니다. :-)

purple% cat > t1.c
void f(float);

int main(void)
{
    f(3.14159f);

    return 0;
}
purple% cat > t2.c
#include <stdio.h>

void f(a)
float a;
{
    printf("%f\n", a);    
}
purple% cat > t.c
#include <stdio.h>

void f(float);

int main(void)
{
    f(3.14159f);

    return 0;
}

void f(a)
float a;
{
    printf("%f\n", a);
}
purple% gcc t.c
purple% ./a.out
3.141590
purple% gcc t1.c t2.c
purple% ./a.out
50.123535
purple% cc t.c
"t.c", line 13: identifier redeclared: f
        current : function() returning void
        previous: function(float) returning void : "t.c", line 3
cc: acomp failed for t.c

위에서 보시면 아시겠지만, gcc 는 참 똑똑한 컴파일러입니다. 하지만,
프로그래머의 잘못(undefined behavior)을 조용히 덮어주는 것만이 능사는
아니라는 것을 gcc 도 알 필요가 있다고 생각합니다.

f() 의 매개변수 데이터형을 float-double 쌍이 아닌 short int-int 쌍으로
테스트하면 분할 컴파일 하는 경우에도 제대로 동작하는 경우가 많습니다.
이유는 전달되는 인자 데이터형의 크기가 word 크기보다 큰가 아닌가 혹은
정수형인가 부동형인가의 문제였던 것으로 기억하고 있습니다. 즉, 실행
환경의 calling convention 이나 기타 다른 특성에 크게 의존하는 부분인
셈입니다.

word 단위가 아닌 실제 데이터형의 크기 그대로 전달하는 경우에도 byte
order 에 따라 little endian 이 더 너그럽게 받아들일 가능성이 큽니다
(이와 관련된 예를 제 책의 연습문제에 넣었던 것으로 기억합니다). 이
경우도 이것이 장점인지 단점인지는 생각하는 관점에 따라 다릅니다; 저는
개인적으로 단점이라고 주장하고 싶습니다.

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

체스맨의 이미지

:)

약간 해프닝 같지만, 다시 원점으로 돌아와서, 처음 글에 제시한 매크로를 그대로 사용하기로 다시 방향을 바꿨습니다.

몇년전 저 매크로를 정의할 당시에 가장 중요한 의도가 "섞어쓰면 안된다" 였습니다. 저 매크로 안에는 그 의도가 담겨있지요. 흐흐... -_-;

Quote:

"지금" 개발되는 프로그램들이 구식 선언을 고려해야 하는
것인지 궁금합니다.

고려해야 한다고 말씀드린 게 아니라, 고려하고 싶다고 말씀드렸지요.
단지, 저 대안을 마련한 당시의 제 의도를 잠시 망각했습니다.
잠시 착각이 있었습니다만, 섞어쓰면 좋지 않습니다. :wink:

Orion Project : http://orionids.org

댓글 달기

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