· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
CLanguage Variable Arguments List

C¾ð¾î °¡º¯ ÀÎÀÚ


printf()¿Í scanf()¿Í °°Àº °¡º¯ ÀÎÀÚ¸¦ ¹Þ´Â ÇÔ¼ö¸¦ ¸¸µé°Å³ª ÀÌ ÇÔ¼ö¸¦ µ¤¾î ¾²´Â wrapper¸¦ ¸¸µé·Á¸é °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÒ ÁÙ ¾Ë¾Æ¾ß ÇÕ´Ï´Ù.

°¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÒ·Á¸é ´ÙÀ½°ú °°Àº data type°ú ÇÔ¼ö (¶Ç´Â ¸ÅÅ©·Î ÇÔ¼ö)¸¦ ½á¾ß ÇÕ´Ï´Ù:

  • va_list -- type
  • va_start(va_list argptr, last-arg) -- °¡º¯ ÀÎÀÚ Ã³¸® ½ÃÀÛ.
  • va_end(va_list argptr) -- °¡º¯ ÀÎÀÚ Ã³¸® ³¡.
  • T va_arg(va_list argptr, T) -- °¡º¯ ÀÎÀÚ ¾ò±â.

À̵éÀº ¸ðµÎ Ç¥ÁØ Çì´õ ÆÄÀÏÀÎ <stdarg.h>¿¡ ¼±¾ðµÇ¾î ÀÖ½À´Ï´Ù. ÀÏ´Ü °£´ÜÈ÷ N°³ÀÇ Á¤¼ö(int type)¸¦ ¹Þ¾Æ¼­ ´õÇÏ´Â ÇÔ¼ö¸¦ ¸¸µé¾î º¾½Ã´Ù:

#include <stdarg.h>

int
sum(int nargs, ...)
{
  va_list argptr;
  int i, total = 0;

  va_start(argptr, nargs);        /* °¡º¯ ÀÎÀÚ Ã³¸® ½ÃÀÛ */
  for (i = 0; i < nargs; i++)
    total += va_arg(argptr, int); /* Çϳª¾¿ °¡º¯ ÀÎÀÚ ¾ò±â */
  va_end(argptr);                 /* °¡º¯ ÀÎÀÚ Ã³¸® ³¡ */

  return total;
}


À§¿Í °°ÀÌ Á¤ÀÇÇØ ³õ°í ´ÙÀ½°ú °°ÀÌ ¾µ ¼ö ÀÖ½À´Ï´Ù (ÁÖÀÇ: sum()ÀÇ Ã¹¹ø° ÀÎÀÚ´Â µÎ¹ø°ºÎÅÍ ³ª¿Ã °¡º¯ ÀÎÀÚÀÇ °¹¼öÀÔ´Ï´Ù):

int sum(int nargs, ...);

int
main(void)
{
  int s1, s2;

  /* 1ºÎÅÍ 5±îÁö ´õÇÑ °ªÀ» s1¿¡ ÀúÀå. */
  s1 = sum(5, 1, 2, 3, 4, 5);

  /* 100, 200, 300À» ´õÇÑ °ªÀ» s2¿¡ ÀúÀå. */
  s2 = sum(3, 100, 200, 300);

  /* ... */
  return 0;
}


ÀÏ´Ü °¡º¯ ÀÎÀÚ¸¦ ó¸®Çϱâ À§Çؼ­´Â va_list typeÀÇ º¯¼ö Çϳª¸¦ ¼±¾ðÇØ¾ß ÇÕ´Ï´Ù:

va_list argptr;


±×¸®°í, °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÒ ºÎºÐ ¾Õ¿¡ ´ÙÀ½°ú °°ÀÌ ½á ÁÝ´Ï´Ù:

va_start(argptr, nargs);


va_start()ÀÇ Ã¹¹ø° ÀÎÀÚ´Â ¾Æ±î ¼±¾ðÇÑ va_list typeÀÇ º¯¼ö À̸§À̸ç, µÎ¹ø° ÀÎÀÚ´Â ÀÌ ÇÔ¼ö¿¡¼­ °¡º¯ ÀÎÀÚ¸¦ ¹Þ´Â ºÎºÐÀÇ ¹Ù·Î ¾ÕÀÇ (°íÁ¤µÈ) argumentÀÔ´Ï´Ù. Áï, À§¿¡¼­ ¿¹·Î µç sum()ÀÇ °æ¿ì, °¡º¯ ÀÎÀÚ¸¦ ³ªÅ¸³»´Â "..." ¾Õ¿¡ ¿À´Â argumentÀÎ nargs°¡ µÎ¹ø° ÀÎÀÚ°¡ µË´Ï´Ù.

´«Ä¡°¡ ºü¸¥ ºÐÀº ÀÌ¹Ì ¾Ë°í ÀÖ°ÚÁö¸¸, °¡º¯ ÀÎÀÚ¸¦ ¹Þ´Â ÇÔ¼ö´Â ¿©·¯ °¡Áö Á¦ÇÑÀÌ ºÙ½À´Ï´Ù. ù°, va_start()¿¡ °¡º¯ ÀÎÀÚ ¹Ù·Î ¾ÕÀÇ °íÁ¤µÈ ÀÎÀÚ¸¦ ÁÖ¾î¾ß Çϱ⠶§¹®¿¡, °¡º¯ ÀÎÀÚ¸¦ ¹Þ´Â ÇÔ¼ö´Â °íÁ¤µÈ ÀÎÀÚ°¡ Çϳª ÀÌ»ó ³ª¿Í¾ß ÇÕ´Ï´Ù. Áï, void foo(...)¿Í °°Àº ÇÔ¼ö´Â ¸¸µé ¼ö ¾ø½À´Ï´Ù. µÑ°, °¡º¯ ÀÎÀÚ¸¦ ³ªÅ¸³»´Â "..."´Â ¹Ýµå½Ã ¸¶Áö¸· ÀÎÀÚÀ̾î¾ß ÇÕ´Ï´Ù. "..."°¡ Áß°£À̳ª óÀ½¿¡ ³ª¿Ã ¼ö´Â ¾ø½À´Ï´Ù. ¿¹¸¦ µé¾î void bar(..., int a)¿Í °°Àº ÇÔ¼ö´Â ¸¸µé ¼ö ¾ø½À´Ï´Ù.

½ÇÁ¦ ÇÔ¼ö¿¡ Àü´ÞµÈ °¡º¯ ÀÎÀÚ¸¦ ¾ò±â À§Çؼ­´Â va_arg()¸¦ ºÒ·¯¼­ ó¸®ÇÕ´Ï´Ù. va_arg()´Â °¡º¯ ÀÎÀÚ·Î Àü´ÞµÈ °ªÀ» È£ÃâÇÒ ¶§¸¶´Ù Çϳª¾¿ ¾ò¾î¼­ ÁÝ´Ï´Ù. va_arg()´Â ù¹ø° ÀÎÀÚ·Î, va_start()·Î ÃʱâÈ­ÇÑ va_list typeÀ» ¹ÞÀ¸¸ç, µÎ¹ø° ÀÎÀڷδ °¡º¯ ÀÎÀÚ·Î Àü´ÞµÈ °ªÀÇ typeÀ» ½á ÁÖ¾î¾ß ÇÕ´Ï´Ù. ¿ì¸®°¡ ¸¸µç sum()ÀÇ °æ¿ì, ÇÔ¼öÀÇ ¸ñÀûÀÌ ¸ðµç int¸¦ ´õÇÑ °ªÀ» °è»êÇÏ´Â °ÍÀ̹ǷÎ, va_arg()ÀÇ µÎ¹ø° ÀÎÀÚ·Î int¸¦ ÁÖ¸é µË´Ï´Ù.

va_arg(argptr, int);


´«Ä¡°¡ ´õ¿í ºü¸¥ ºÐÀÌ¸é ¾Æ½Ã°ÚÁö¸¸, ¿©±â¼­ °¡º¯ ÀÎÀÚ¸¦ ¹Þ´Â ÇÔ¼ö¿¡ ¶Ç´Ù¸¥ Á¦ÇÑÀÌ ºÙ½À´Ï´Ù. ¾Æ½Ã°ÚÁö¸¸, °¡º¯ ÀÎÀÚ·Î Àü´ÞµÇ´Â °ªÀÇ Å¸ÀÔ¿¡´Â Á¦ÇÑÀÌ ¾ø½À´Ï´Ù (printf(), scanf()¸¦ »ý°¢Çغ¸¼¼¿ä). ¾Æ½±°Ôµµ va_arg()´Â Àü´ÞµÇ´Â °ªÀÇ Å¸ÀÔÀ» ¾Ë¾Æ³¾ ¹æ¹ýÀÌ ¾ø½À´Ï´Ù. µû¶ó¼­ ¹Ì¸® ±× typeÀ» ¾Ë¾Æ¼­ va_arg()ÀÇ µÎ¹ø° ÀÎÀÚ·Î Àü´ÞÇØ ÁÖ¾î¾ß ÇÕ´Ï´Ù.

°Ô´Ù°¡, °¡º¯ ÀÎÀÚ¸¦ ¹Þ´Â ÇÔ¼öÀÇ ÀÔÀå¿¡¼­, ¸î°³ÀÇ °¡º¯ ÀÎÀÚ°¡ Àü´ÞµÇ¾ú´ÂÁö ¾Ë¾Æ³¾ ¹æ¹ýÀº ¾ø½À´Ï´Ù. µû¶ó¼­ °íÁ¤µÈ ÀÎÀÚ·Î °¡º¯ ÀÎÀÚÀÇ °¹¼ö¸¦ Àü´ÞÇÏ´Â µî (À§ÀÇ sum()ÀÇ ¿¹Ã³·³)ÀÇ ¹æ¹ýÀ¸·Î va_arg()¸¦ ¸î¹øÀ» ºÒ·¯¾ß µÇ´Â°¡¸¦ ¾Ë¾Æ³¾ ¹æ¹ýÀ» Á¦°øÇØ¾ß ÇÕ´Ï´Ù.

´õ °ñÄ¡ ¾ÆÇ °ÍÀº va_arg()ÀÇ µÎ¹ø° ÀÎÀÚ·Î ¾µ ¼ö ÀÖ´Â type¿¡ Á¦ÇÑÀÌ ÀÖ´Ù´Â °ÍÀÔ´Ï´Ù. ÀÌ°Ç µÚ¿¡¼­ ´Ù·ç°Ú½À´Ï´Ù.

ÀÌÁ¦ °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÏ´Â ÇÔ¼ö¸¦ ¸¸µé¾î º¸¾ÒÀ¸´Ï, printf()ÀÇ wrapper¸¦ ¸¸µé¾î º¾½Ã´Ù.

³ëÆĽɿ¡¼­ ¸»¾¸µå¸®Áö¸¸, ´ÙÀ½°ú °°Àº ÇÔ¼ö´Â µ¿ÀÛÇÏÁö ¾Ê½À´Ï´Ù:

int
my_printf(const char *fmt, ...)
{
  return printf(fmt, ...);
}


ÀÏ´Ü ¸ÕÀú, printfÀÇ °è¿­¿¡´Â ´ÙÀ½°ú °°Àº ÇÔ¼öµéÀÌ ÀÖ´Ù´Â °ÍÀ» ¾Ë¾ÆµÓ½Ã´Ù:

int printf(const char *fmt, ...);
int fprintf(FILE fp, const char *fmt, ...);
int sprintf(char *sr, const char *fmt, ...);
int snprintf(char *s, size_t n, const char *fmt, ...);
/* ÀÌ»ó <stdio.h>¿¡ ¼±¾ðµÇ¾î ÀÖ´Â ÇÔ¼öµé */

int vprintf(const char *fmt, va_list ap);
int vfprintf(FILE fp, const char *fmt, va_list ap);
int vsprintf(char *sr, const char *fmt, va_list ap);
int vsnprintf(char *s, size_t n, const char *fmt, va_list ap);
/* ÀÌ»ó <stdarg.h>¿¡ ¼±¾ðµÇ¾î ÀÖ´Â ÇÔ¼öµé */


Àß º¸¸é ¾Ë°ÚÁö¸¸, <stdarg.h>¿¡ ÀÖ´Â ÇÔ¼öµéÀº <stdio.h>¿¡ ÀÖ´Â printf() °è¿­ ÇÔ¼ö À̸§ ¾Õ¿¡ 'v'°¡ ºÙ°í, "..." ´ë½Å¿¡ va_list typeÀÇ ÀÎÀÚ°¡ ¿Â´Ù´Â °ÍÀ» ¾Ë ¼ö ÀÖ½À´Ï´Ù.

printf() styleÀÇ ¹®ÀÚ¿­À» ¹ÞÀ¸·Á¸é, ÀÌ v*printf() °è¿­ÀÇ ÇÔ¼ö¸¦ ¾²¸é Æí¸®ÇÕ´Ï´Ù. ¿¹¸¦ µé¾î ´Ü¼øÈ÷ printf()¿Í ¶È°°Àº ±â´ÉÀ» ÇÏ´Â wrapper´Â ´ÙÀ½°ú °°ÀÌ ¸¸µé ¼ö ÀÖ½À´Ï´Ù:

int
my_printf(const char *fmt, ...)
{
  va_list argptr;
  int ret;

  va_start(argptr, fmt);
  ret = vprintf(fmt, argptr);
  va_end(argptr);

  return ret;
}


Áï, °¡º¯ ÀÎÀÚ Ã³¸®¸¦ À§ÇÑ va_list type º¯¼ö¸¦ ¼±¾ð, va_start()·Î ÃʱâÈ­ÇÑ ´ÙÀ½¿¡ v*printf() °è¿­ÀÇ ÇÔ¼ö¿¡ ÀÌ va_list typeÀÇ º¯¼ö¸¦ ³Ñ°ÜÁֱ⸸ ÇÏ¸é µË´Ï´Ù. (va_end()¸¦ ºÒ·¯ ³¡³»´Â °ÍÀ» ÀØÁö ¸¶¼¼¿ä!!)

Á»´õ º¹ÀâÇÏ°Ô Çϳª ´õ ¸¸µé¾î º¾½Ã´Ù. ÇÔ¼ö´Â error()ÀÔ´Ï´Ù. ÀÌ ÇÔ¼ö´Â ÁÖ¾îÁø printf() styleÀÇ ¿¡·¯ ¸Þ½ÃÁö¸¦ ¹Þ¾Æ¼­ stderr·Î Ãâ·ÂÇÏ°í, ÇÊ¿äÇϸé errnoÀÇ ³»¿ëµµ ¾Ë·ÁÁÖ°í, ÇÊ¿äÇϸé exit()¸¦ ºÒ·¯¼­ ÇÁ·Î±×·¥À» Á¾·áÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. ¼±¾ðÀº ´ÙÀ½°ú °°½À´Ï´Ù:

void error(int status, int ecode,
           const char *fmt, ...);


ÀÌ ÇÔ¼ö´Â ecode°¡ 0ÀÌ ¾Æ´Ñ °æ¿ì, strerror(ecode) °ªÀ» Ãâ·ÂÇÏ°í, fmt¿Í "..."À¸·Î Àü´ÞµÈ printf() styleÀÇ ¿¡·¯ ¸Þ½ÃÁöµµ Ãâ·ÂÇÑ ´ÙÀ½, status°¡ 0ÀÌ ¾Æ´Ñ °æ¿ì, exit(status)¸¦ È£ÃâÇÕ´Ï´Ù. ÇÔ¼ö Á¤ÀÇ´Â ´ÙÀ½°ú °°½À´Ï´Ù.

void
error(int status, int ecode,
      const char *fmt, ...)
{
  va_list argptr;

  fflush(stdout);
  fprintf(stderr, "error: ");
  if (ecode)
    fprintf(stderr, "%s: ", strerror(ecode));

  va_start(argptr, fmt);
  vfprintf(stderr, fmt, argptr);
  va_end(argptr);

  fputc('\n', stderr);

  fflush(stderr);  /* redundant */

  if (status)
    exit(status);
}


´ÙÀ½°ú °°ÀÌ ¾µ ¼ö ÀÖ½À´Ï´Ù.

#include <stdio.h>
#include <errno.h>

...

void
foo(const char *filename)
{
  FILE *fp;
  fp = fopen(filename, "r");
  if (!fp)
    error(1, errno, "cannot open file %s.", filename);
  ...
}


Âü°í·Î ¿©±â¼­ ¿¹·Î ¸¸µç error()´Â GNU C library (glibc)¿¡ ÀÌ¹Ì Æ÷ÇԵǾî ÀÖ½À´Ï´Ù. ¿©±â¿¡¼­´Â Á»´õ °£·«È­Çؼ­ ¸¸µé¾î º» °ÍÀÌÁÒ. ½ÇÁ¦ ¿©·¯ºÐÀÇ Äڵ忡 <error.h>¸¦ Æ÷ÇÔ½ÃÅ°¸é À§ error()¸¦ Á¤ÀÇÇÒ ÇÊ¿ä¾øÀÌ ¹Ù·Î ¾µ ¼ö ÀÖ½À´Ï´Ù. (Ãâ·Â ÇüÅ´ ¾à°£ ´Ù¸¦ ¼ö ÀÖ½À´Ï´Ù¸¸, ÀÎÀÚ typeÀ̳ª °¹¼ö´Â °°À¸´Ï ¶È°°ÀÌ ¾µ ¼ö ÀÖ½À´Ï´Ù)

¸¶Áö¸·À¸·Î ¾Æ±î va_arg()ÀÇ µÎ¹ø° ÀÎÀÚ·Î ³ª¿Ã ¼ö ÀÖ´Â type¿¡ Á¦ÇÑÀÌ ÀÖ´Ù°í Çߴµ¥ ±× ¾ê±â¸¦ Çغ¸°Ú½À´Ï´Ù. °á·ÐºÎÅÍ ¸»Çϸé, va_arg()ÀÇ µÎ¹ø° ÀÎÀÚ·Î ³ª¿Ã ¼ö ÀÖ´Â typeÀº ´ÙÀ½°ú °°½À´Ï´Ù:

  • int °è¿­ (int, unsigned int, signed int)
  • long °è¿­ (long, unsigned long, signed long)
  • double °è¿­ (double, long double)
  • Æ÷ÀÎÅÍ °è¿­ (¸ðµç ŸÀÔÀÇ Æ÷ÀÎÅÍ, ¿¹¸¦ µé¾î void *, char *, µîµî)

´ÙÀ½°ú °°Àº ŸÀÔÀº ¿Ã ¼ö ¾ø½À´Ï´Ù:

  • char °è¿­ (char, unsigned char, signed char)
  • short °è¿­ (short, unsigned short, signed short)
  • float °è¿­ (float)

±×·³ °¡º¯ ÀÎÀÚ·Î char³ª float typeÀº ¿Ã ¼ö ¾ø´À³Ä, ±×·¸Áö´Â ¾Ê½À´Ï´Ù. ÀÌ·± ŸÀÔÀ» ¹Þ±â À§Çؼ­´Â, va_arg()¿¡ ´ÙÀ½°ú °°ÀÌ Àü´ÞÇÕ´Ï´Ù.

  • char -> int (unsigned char´Â unsigned int, ÀÌ·± ½ÄÀ¸·Î)
  • short -> int (unsigned short´Â unsigned short, ÀÌ·± ½ÄÀ¸·Î)
  • float -> double

±× ÀÌÀ¯´Â ´ÙÀ½°ú °°½À´Ï´Ù. C ¾ð¾î°¡ óÀ½ ¸¸µé¾îÁú ¶§¿¡´Â function prototypeÀ̶õ°Ô ¾ø¾ú½À´Ï´Ù. ÀÎÀÚ°¡ ¸î°³ÀÌ°í, ¾î¶² ŸÀÔÀ̳Ŀ¡ »ó°ü¾øÀÌ ´Ü¼øÈ÷ ÇÔ¼ö°¡ ÀÖ°í, ¸®ÅÏ Å¸ÀÔÀÌ ¹¹´Ù. Á¤µµ¸¸ ¾Ë·Á ÁáÁÒ. ¿¹¸¦ µé¸é ´ÙÀ½°ú °°½À´Ï´Ù:

double bar();

double bar(a, f, ch)
  int a;
  float f;
  char ch;
{
  ...
}


ÀÌ·± ½ÄÀ¸·Î ÇÔ¼ö¸¦ ¼±¾ðÇÏ°Ô µÇ¸é, ÄÄÆÄÀÏ·¯°¡ ÇÔ¼öÀÇ Á¤ÀǸ¦ º¸±â Àü¿¡´Â ÀÌ ÇÔ¼ö¿¡ Àü´ÞµÇ´Â ÀÎÀÚÀÇ Å¸ÀÔÀÌ ¹ºÁö ¾Ë ¼ö ¾ø½À´Ï´Ù. ¸¸¾à ÄÄÆÄÀÏ·¯°¡ bar()ÀÇ Á¤ÀǸ¦ º¸±â Àü¿¡ ´ÙÀ½°ú °°Àº Äڵ带 ÄÄÆÄÀÏÇØ¾ß ÇÑ´Ù°í °¡Á¤ÇØ º¸±â ¹Ù¶ø´Ï´Ù:

void
foo(void)
{
  bar(4, 2.5, 9);
}


ÀÏ´Ü bar()ÀÇ ÀÎÀÚ°¡ 3°³Àε¥,, "void bar();"¸¸ º¸°í¼­´Â ÀÎÀÚ°¡ ÀûÀýÇÏ°Ô Àü´ÞµÇ¾ú´ÂÁö ¾Ë ¹æ¹ýÀÌ ¾ø½À´Ï´Ù. µû¶ó¼­ ÀÎÀÚ °¹¼ö üũ¸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù.

µÑ°·Î, °¢°¢ÀÇ ÀÎÀÚ°¡ ¾Ë¸Â´Â ŸÀÔÀÎÁöµµ ¾Ë ¼ö ¾ø½À´Ï´Ù. ÇÔ¼ö È£ÃâÀ» À§Çؼ­´Â (stack¿¡ ÀÎÀÚ¸¦ pushÇØ¾ß Çϴµ¥), ÀÎÀÚÀÇ typeÀ» ¾Ë ¼ö ¾øÀ¸´Ï, ù¹ø° ÀÎÀÚÀÎ 4¸¦ pushÇÒ ¶§, 8 bit·Î 4¸¦ pushÇÒ °ÍÀÎÁö, 16 bit·Î 4¸¦ pushÇÒ °ÍÀÎÁö, 32 bit·Î ÇÒ °ÍÀÎÁö ¾Ë ¼ö°¡ ¾ø½À´Ï´Ù.

µû¶ó¼­ C ¾ð¾î¿¡´Â "integral promotion"À̶õ ¿ë¾î? °³³ä?ÀÌ ÀÖ°í, ¿©±â¿¡ µû¶ó¼­ ¸ðµç ÀÎÀÚ´Â ´ÙÀ½°ú °°Àº typeÀ¸·Î º¯È¯Çؼ­ stack¿¡ pushÇÕ´Ï´Ù.

  • char, short -> int
  • float -> double
  • int -> int (±×´ë·Î)
  • long -> long (±×´ë·Î)
  • double -> double (±×´ë·Î)
  • long double -> long double (±×´ë·Î)
  • ¸ðµç pointer type -> ¸ðµç pointer type (±×´ë·Î)

Áï, ÀÎÀÚ·Î Àü´ÞµÈ °ªÀÌ character °ªÀ̶ó ÇÒ Áö¶óµµ ÇÔ¼ö¸¦ È£ÃâÇÒ ¶§¿¡´Â int typeÀ¸·Î º¯È¯Çؼ­ Àü´ÞÇÕ´Ï´Ù.

Áö±Ý±îÁö´Â ANSI C¿¡¼­ function prototypeÀÌ ³ª¿À±â ÀüÀÇ old style (K&R) C¿¡ ÇÊ¿äÇÑ ³»¿ëÀÔ´Ï´Ù. ÀÚ, ANSI C¿¡¼­´Â function prototypeÀÌ ÀÖÀ¸´Ï, ÄÄÆÄÀÏ·¯°¡ ÇÔ¼ö È£ÃâÀ» Çϱâ Àü¿¡ ÇÔ¼öÀÇ ÀÎÀÚ °¹¼ö¿Í ŸÀÔÀ» ¸ðµÎ ¾Ë ¼ö ÀÖ½À´Ï´Ù.

double bar(int a, float f, char ch);


µû¶ó¼­ ´õ ÀÌ»ó ÀÌ·¯ÇÑ º¯È¯ÀÌ ÇÊ¿ä¾ø°Ô µÇ¾úÁö¸¸, Çϳª ¿¹¿Ü°¡ Àִµ¥, ¹Ù·Î °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. °¡º¯ ÀÎÀÚ´Â ½ÇÁ¦·Î ¾î¶°ÇÑ Å¸ÀÔÀÌ ¸î°³°¡ µé¾î¿Ã Áö ¾Ë ¼ö ¾ø±â ¶§¹®¿¡, ÀÌ·¯ÇÑ º¯È¯ÀÌ °è¼Ó ¼öÇàµË´Ï´Ù. µû¶ó¼­ va_arg()·Î ÀÌ·¯ÇÑ Å¸ÀÔÀ» ¹ÞÀ»·Á¸é ÀÌ integral conversionÀ» ¹Ì¸® »ý°¢ÇØ µÎ¾î¾ß ÇÕ´Ï´Ù.

¿¹¸¦ µé¾î ¹®ÀÚ Çϳª¾¿ ¹Þ¾Æ¼­ Ãâ·ÂÇÏ´Â ÇÔ¼ö¸¦ ¸¸µé¾î º¸°Ú½À´Ï´Ù:

void
putchars(int nargs, ...)
{
  va_list argptr;
  char ch;
  int i;

  va_starg(argptr, nargs);
  for (i = 0; i < nargs; i++) {
    ch = (char) va_arg(argptr, int);
    putchar(ch);
  }
  va_end(argptr);
}


Áï, µé¾î¿Ã °¡º¯ ÀÎÀÚ°¡ char typeÀÏÁö¶óµµ va_arg()¿¡¼­´Â integral promotion¿¡ µû¶ó int typeÀ¸·Î ¹Þ¾Æ¼­ ó¸®ÇØ¾ß ÇÕ´Ï´Ù.

Àß »ý°¢ÇØ º¸¸é, ÀÌ¹Ì ¿©±â¿¡ ´ëÇØ ¾Ë°í ÀÖ¾úÀ» °ÍÀÔ´Ï´Ù. printf()¿Í scanf()¸¦ »ý°¢Çغ¾½Ã´Ù.

printf¿¡¼­ floatÀ̳ª doubleÀ» Ãâ·ÂÇϱâ À§Çؼ­´Â "%f"¸¦ ¾¹´Ï´Ù. ±×·±µ¥, scanf¿¡¼­´Â floatÀº "%f", doubleÀº "%lf"¸¦ ¾¹´Ï´Ù. ¾Æ·¡ ¿¹ Âü°í:

double d;
float f;

printf("%f", d);
printf("%f", f);

scanf("%f", &f);
scanf("%lf", &d);


±× ÀÌÀ¯´Â, integral promotino¿¡ ÀÇÇØ printfÀÇ °æ¿ì, floatÀ» double·Î ¹Þ±â ¶§¹®ÀÔ´Ï´Ù. µû¶ó¼­ float°ú double¿¡ °üÇÑ Â÷ÀÌ°¡ ¾ø½À´Ï´Ù. ±×·¯³ª scanfÀÇ °æ¿ì¿¡´Â ¸ðµç ÀÎÀÚ°¡ pointer typeÀ̱⠶§¹®¿¡ ÀÌ·¯ÇÑ º¯È¯ÀÌ ÇÊ¿ä¾ø½À´Ï´Ù. Áï, ¸ðµç ŸÀÔÀ» °¢°¢ ±¸º°ÇØ¾ß ÇÏ´Â °ÍÀÌÁÒ.

ºÐ¸í printf ÄÚµå¾È¿¡¼­ floatÀ» Ãâ·ÂÇÏ´Â ºÎºÐÀº ´ÙÀ½°ú °°Àº Äڵ带 Æ÷ÇÔÇÕ´Ï´Ù:

  value = (float) va_arg(argptr, double);


¶ÇÇÑ scanf ÄÚµå ¾È¿¡¼­ floatÀ» Ãâ·ÂÇÏ´Â ºÎºÐÀº ´ÙÀ½°ú °°Àº Äڵ带 Æ÷ÇÔÇÕ´Ï´Ù:

  ptr = va_arg(argptr, float *);


ÀÌ Á¤µµ¸é °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÏ´Â ¹æ¹ýÀº ¿Ïº®È÷! ÀÍÈ÷¼ÌÀ» °ÍÀÔ´Ï´Ù. ±×·³ ´ÙÀ½ ±âȸ¿¡...

³¡ -- cinsk



  • TODO: Function prototypeÀÌ ANSI C¿¡¼­ ¼Ò°³µÈ °Í ¸Â³ª?
  • TODO: Integral PromotionÀ̶ó°í Çߴµ¥, ¿©±â¿¡ float, doubleÀÌ Æ÷ÇԵǴ °ÍÀÌ È®½ÇÇÑ°¡?
ÀÌ°Å ¾Ë¾Æº¸°í ±Û °íÄ¥ °Í.. -- cinsk.

ÇÔ¼ö ¼±¾ð(Á¤ÀÇ°¡ ¾Æ´Ñ)ÀÇ °æ¿ì¿¡´Â ±× Àü¿¡µµ ÀÖ¾ú´ø °Í °°½À´Ï´Ù. [http]http://www.ifi.uio.no/forskning/grupper/dsb/Programvare/Xite/ProgrammersManual/node11.html#SECTION000111000000000000000 ±×·¯³ª ¸Å°³º¯¼öÀÇ Å¸ÀÔµéÀ» ÇÔ²² Àû¾îÁÖ´Â function prototypeÀº ANSI C¿¡¼­ »õ·ÎÀÌ ³ª¿Â °ÍÀÎ µí ÇÕ´Ï´Ù.

°¡º¯ÀÎÀÚ ÇÔ¼ö¿¡¼­ Àû¿ëµÇ´Â °ÍÀº Integral PromotionÀ» Æ÷ÇÔÇÏ´Â Default argumnt promotionÀÔ´Ï´Ù.

C99 6.5.2.2 Function calls Áß¿¡¼­...

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.

±×¸®°í Ç¥Áع®¼­¿¡¼­´Â Integer promotionÀ̶ó´Â ¿ë¾î¸¦ ¾¹´Ï´Ù.

Integer promotionÀº À̸§ ±×´ë·Î Á¤¼öÇüÀÇ ½Â±Þ¸¸À» ÀǹÌÇÕ´Ï´Ù. doubleÀ̳ª Æ÷ÀÎÅÍ´Â Æ÷ÇÔµÇÁö ¾Ê½À´Ï´Ù. intÇü ¶Ç´Â unsigned intÇüº¸´Ù rank°¡ ³·Àº (Áï Ç¥Çö¹üÀ§°¡ Á¼Àº) Á¤¼öÇü¿¡ ÇÑÇؼ­ int Çü ¶Ç´Â unsigned ÇüÀ¸·Î ½Â±ÞµË´Ï´Ù. ÇØ´çµÇÁö ¾Ê´Â µ¥ÀÌÅÍ ÇüµéÀº ±×´ë·Î ³²½À´Ï´Ù.

6.3.1.1 Boolean, characters, and integers Áß¿¡¼­...

The following may be used in an expression wherever an int or unsigned int may be used:

  • An object or expression with an integer type whose integer conversion rank is less than the rank of int and unsigned int.
  • A bit-field of type _Bool, int, signed int, or unsigned int.

If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.



°¡º¯ ÀÎÀÚ ¸ÅÅ©·Î


ISO C Ç¥ÁØÀ» Áö¿øÇÏ´Â ÄÄÆÄÀÏ·¯¿¡¼­´Â °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÏ´Â ¸ÅÅ©·Îµµ Á¤ÀÇÇÒ ¼ö ÀÖ½À´Ï´Ù. ÇÔ¼ö ÇüÅÂÀÇ ¸ÅÅ©·Î¸¦ Á¤ÀÇÇÒ ¶§, "..."À» ½á ÁÖ°í, ¸ÅÅ©·Î Á¤ÀÇ ºÎºÐ¿¡¼­ VA_ARGS¸¦ ½áÁÖ¸é ±× ÀÚ¸®¿¡ È®ÀåµË´Ï´Ù. ¿¹¸¦ µé¸é, ´ÙÀ½°ú °°½À´Ï´Ù:

#define debug(s, ...)    fprintf(stderr, s, __VA_ARGS__)

void
foo(void)
{
  debug("Entered the function, %s\n", __func__);
  /* ... */
}


°£´ÜÇÏ°Ô printf ÇüÅÂÀÇ ¸Þ½ÃÁö¸¦ ÀԷ¹ÞÀº Ç¥ÁØ ÇÔ¼ö assert()¿Í ºñ½ÁÇÑ ¸ÅÅ©·Î ÇÔ¼ö¸¦ ¸¸µé¾î º¾½Ã´Ù; ÇÔ¼ö À̸§Àº ASSERT()·Î ÇÏ°Ú½À´Ï´Ù. ASSERT()ÀÇ Ã¹ ÀÎÀÚ´Â, assert()ÀÇ ÀÎÀÚ¿Í °°½À´Ï´Ù. Áï °ÅÁþÀÎ °æ¿ì, abort()¸¦ ºÎ¸¨´Ï´Ù. ASSERT()ÀÇ µÎ¹ø° ÀÎÀÚºÎÅÍ´Â printf()¿Í °°½À´Ï´Ù. ¶ÇÇÑ NDEBUG ¸ÅÅ©·Î°¡ Á¤ÀÇµÈ °æ¿ì, ASSERT()´Â ¾Æ¹«·± ¿µÇâÀ» ÁÖÁö ¾Ê½À´Ï´Ù.

ÀÏ´Ü, ASSERT()°¡ ¾²ÀÎ ½ÃÁ¡ÀÇ ÆÄÀÏ À̸§, ÁÙ ¹øÈ£, ±×¸®°í ÇÔ¼ö À̸§À» ÀÚµ¿À¸·Î Ãâ·ÂÇÏ°Ô ÇսôÙ. µû¶ó¼­ ¹Ì¸® Á¤ÀÇµÈ ¸ÅÅ©·ÎÀÎ FILE°ú LINEÀ» ¾²¸ç, ¹Ì¸® Á¤ÀÇµÈ À̸§, func¸¦ ¾¹´Ï´Ù.

¾Æ·¡¿¡ ASSERT()ÀÇ Á¤ÀÇ°¡ ³ª°©´Ï´Ù:

#ifndef NDEBUG
# define ASSERT(exp, s, ...)  assert_(__FILE__, __LINE__, __func__, \
                                      #exp, s, __VA_ARGS__)
#else
# define ASSERT(exp, s, ...)  ((void)0)
#endif /* NDEBUG */


°£´ÜÇÕ´Ï´Ù. NDEBUG°¡ Á¤ÀÇµÈ °æ¿ì¿¡´Â ASSERT()°¡ assert_()¸¦ È£ÃâÇÕ´Ï´Ù. assert_()ÀÇ Ã³À½ ¼¼ ÀÎÀÚ´Â ASSERT()¸¦ ºÎ¸¥ °÷ÀÇ ÆÄÀÏ À̸§, ÁÙ ¹øÈ£, ÇÔ¼ö À̸§À» ÀÚµ¿À¸·Î Àü´ÞÇÏ°Ô µË´Ï´Ù. ´ÙÀ½À¸·Î ASSERT()ÀÇ Ã¹ ÀÎÀÚ¸¦ ¹®ÀÚ¿­·Î ¹Ù²Ù¾î Àü´ÞÇϸç(#exp), ±× ´ÙÀ½À¸·Î, printf() ½ºÅ¸ÀÏÀÇ format stringÀÎ s°¡ µé¾î¿À¸ç, ±× µÚ¿¡ °¡º¯ ÀÎÀÚ°¡ µé¾î¿É´Ï´Ù.

ÀÌÁ¦ assert_()ÀÇ Á¤ÀÇ°¡ ³ª°©´Ï´Ù:

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

void
assert_(const char *filename, int lineno, const char *func,
        const char *exp, const char *fmt, ...)
{
  va_list argptr;

  fflush(stdout);
  fprintf(stderr, "%s:%d: assertion, (%s) failed in function, %s\n",
          filename, lineno, exp, func);
  fprintf(stderr, "\treason: ");
  va_start(argptr, fmt);
  vfprintf(stderr, fmt, argptr);
  va_end(argptr);
  putc('\n', stderr);
  abort();
}


¿¹¸¦ µé¾î ´ÙÀ½ ÇÔ¼ö¸¦ »ý°¢ÇØ º¾½Ã´Ù:
void
set_age(int age)
{

ASSERT(age > MIN_AGE, "age should be larger than %d.", MIN_AGE);
/* ... */

}
MIN_AGE´Â 10À¸·Î Á¤ÀÇµÈ ¸ÅÅ©·ÎÀÌ°í, »ç¿ëÀÚ°¡ set_age(3)À» È£ÃâÇß´Ù¸é, ´ÙÀ½°ú °°Àº ASSERTionÀÌ ¹ß»ýÇÕ´Ï´Ù:

tmp.c:36: assertion, (age > minimum) failed in function, set_age
        reason: age should be larger than 10.
Aborted


ÀÚ, ±×·° Àú·° ASSERT() ¾µ¸¸ÇÏÁÒ? assert()º¸´Ù´Â Á» ³ªÀ» °Í °°½À´Ï´Ù.

Âü°í: ISO C Ç¥ÁØ 6.4.2.2, 6.10.3

±×·³ ¶Ç ´ÙÀ½ ±âȸ¿¡.. -- cinsk



ID
Password
Join
Love is in the offing. Be affectionate to one who adores you.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2005-04-12 22:35:12
Processing time 0.0113 sec