CLanguage Variable Arguments List
C¾ð¾î °¡º¯ ÀÎÀÚ ¶printf()¿Í scanf()¿Í °°Àº °¡º¯ ÀÎÀÚ¸¦ ¹Þ´Â ÇÔ¼ö¸¦ ¸¸µé°Å³ª ÀÌ ÇÔ¼ö¸¦ µ¤¾î ¾²´Â wrapper¸¦ ¸¸µé·Á¸é °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÒ ÁÙ ¾Ë¾Æ¾ß ÇÕ´Ï´Ù.
°¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÒ·Á¸é ´ÙÀ½°ú °°Àº data 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Àº ´ÙÀ½°ú °°½À´Ï´Ù:
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ÇÕ´Ï´Ù.
Áö±Ý±îÁö´Â 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
ÇÔ¼ö ¼±¾ð(Á¤Àǰ¡ ¾Æ´Ñ)ÀÇ °æ¿ì¿¡´Â ±× Àü¿¡µµ ÀÖ¾ú´ø °Í °°½À´Ï´Ù.
![]() °¡º¯ÀÎÀÚ ÇÔ¼ö¿¡¼ Àû¿ëµÇ´Â °ÍÀº 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:
°¡º¯ ÀÎÀÚ ¸ÅÅ©·Î ¶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);
/* ... */
}
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
|
Don't be overly suspicious where it's not warranted. |