== 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) -- °¡º¯ ÀÎÀÚ ¾ò±â. À̵éÀº ¸ðµÎ Ç¥ÁØ Çì´õ ÆÄÀÏÀÎ ¿¡ ¼±¾ðµÇ¾î ÀÖ½À´Ï´Ù. ÀÏ´Ü °£´ÜÈ÷ N°³ÀÇ Á¤¼ö(int type)¸¦ ¹Þ¾Æ¼­ ´õÇÏ´Â ÇÔ¼ö¸¦ ¸¸µé¾î º¾½Ã´Ù: {{{#!vim c #include 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()ÀÇ Ã¹¹ø° ÀÎÀÚ´Â µÎ¹ø°ºÎÅÍ ³ª¿Ã °¡º¯ ÀÎÀÚÀÇ °¹¼öÀÔ´Ï´Ù): {{{#!vim c 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ÀÇ º¯¼ö Çϳª¸¦ ¼±¾ðÇØ¾ß ÇÕ´Ï´Ù: {{{#!vim c va_list argptr; }}} ±×¸®°í, °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÒ ºÎºÐ ¾Õ¿¡ ´ÙÀ½°ú °°ÀÌ ½á ÁÝ´Ï´Ù: {{{#!vim c 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¸¦ ÁÖ¸é µË´Ï´Ù. {{{#!vim c va_arg(argptr, int); }}} ´«Ä¡°¡ ´õ¿í ºü¸¥ ºÐÀÌ¸é ¾Æ½Ã°ÚÁö¸¸, ¿©±â¼­ °¡º¯ ÀÎÀÚ¸¦ ¹Þ´Â ÇÔ¼ö¿¡ ¶Ç´Ù¸¥ Á¦ÇÑÀÌ ºÙ½À´Ï´Ù. ¾Æ½Ã°ÚÁö¸¸, °¡º¯ ÀÎÀÚ·Î Àü´ÞµÇ´Â °ªÀÇ Å¸ÀÔ¿¡´Â Á¦ÇÑÀÌ ¾ø½À´Ï´Ù (printf(), scanf()¸¦ »ý°¢Çغ¸¼¼¿ä). ¾Æ½±°Ôµµ va_arg()´Â Àü´ÞµÇ´Â °ªÀÇ Å¸ÀÔÀ» ¾Ë¾Æ³¾ ¹æ¹ýÀÌ ¾ø½À´Ï´Ù. µû¶ó¼­ ¹Ì¸® ±× typeÀ» ¾Ë¾Æ¼­ va_arg()ÀÇ µÎ¹ø° ÀÎÀÚ·Î Àü´ÞÇØ ÁÖ¾î¾ß ÇÕ´Ï´Ù. °Ô´Ù°¡, °¡º¯ ÀÎÀÚ¸¦ ¹Þ´Â ÇÔ¼öÀÇ ÀÔÀå¿¡¼­, ¸î°³ÀÇ °¡º¯ ÀÎÀÚ°¡ Àü´ÞµÇ¾ú´ÂÁö ¾Ë¾Æ³¾ ¹æ¹ýÀº ¾ø½À´Ï´Ù. µû¶ó¼­ °íÁ¤µÈ ÀÎÀÚ·Î °¡º¯ ÀÎÀÚÀÇ °¹¼ö¸¦ Àü´ÞÇÏ´Â µî (À§ÀÇ sum()ÀÇ ¿¹Ã³·³)ÀÇ ¹æ¹ýÀ¸·Î va_arg()¸¦ ¸î¹øÀ» ºÒ·¯¾ß µÇ´Â°¡¸¦ ¾Ë¾Æ³¾ ¹æ¹ýÀ» Á¦°øÇØ¾ß ÇÕ´Ï´Ù. ´õ °ñÄ¡ ¾ÆÇ °ÍÀº va_arg()ÀÇ µÎ¹ø° ÀÎÀÚ·Î ¾µ ¼ö ÀÖ´Â type¿¡ Á¦ÇÑÀÌ ÀÖ´Ù´Â °ÍÀÔ´Ï´Ù. ÀÌ°Ç µÚ¿¡¼­ ´Ù·ç°Ú½À´Ï´Ù. ÀÌÁ¦ °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÏ´Â ÇÔ¼ö¸¦ ¸¸µé¾î º¸¾ÒÀ¸´Ï, printf()ÀÇ wrapper¸¦ ¸¸µé¾î º¾½Ã´Ù. ³ëÆĽɿ¡¼­ ¸»¾¸µå¸®Áö¸¸, ´ÙÀ½°ú °°Àº ÇÔ¼ö´Â µ¿ÀÛÇÏÁö ¾Ê½À´Ï´Ù: {{{#!vim c int my_printf(const char *fmt, ...) { return printf(fmt, ...); } }}} ÀÏ´Ü ¸ÕÀú, printfÀÇ °è¿­¿¡´Â ´ÙÀ½°ú °°Àº ÇÔ¼öµéÀÌ ÀÖ´Ù´Â °ÍÀ» ¾Ë¾ÆµÓ½Ã´Ù: {{{#!vim c 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, ...); /* ÀÌ»ó ¿¡ ¼±¾ðµÇ¾î ÀÖ´Â ÇÔ¼öµé */ 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); /* ÀÌ»ó ¿¡ ¼±¾ðµÇ¾î ÀÖ´Â ÇÔ¼öµé */ }}} Àß º¸¸é ¾Ë°ÚÁö¸¸, ¿¡ ÀÖ´Â ÇÔ¼öµéÀº ¿¡ ÀÖ´Â printf() °è¿­ ÇÔ¼ö À̸§ ¾Õ¿¡ 'v'°¡ ºÙ°í, "..." ´ë½Å¿¡ va_list typeÀÇ ÀÎÀÚ°¡ ¿Â´Ù´Â °ÍÀ» ¾Ë ¼ö ÀÖ½À´Ï´Ù. printf() styleÀÇ ¹®ÀÚ¿­À» ¹ÞÀ¸·Á¸é, ÀÌ v*printf() °è¿­ÀÇ ÇÔ¼ö¸¦ ¾²¸é Æí¸®ÇÕ´Ï´Ù. ¿¹¸¦ µé¾î ´Ü¼øÈ÷ printf()¿Í ¶È°°Àº ±â´ÉÀ» ÇÏ´Â wrapper´Â ´ÙÀ½°ú °°ÀÌ ¸¸µé ¼ö ÀÖ½À´Ï´Ù: {{{#!vim c 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()¸¦ ºÒ·¯¼­ ÇÁ·Î±×·¥À» Á¾·áÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. ¼±¾ðÀº ´ÙÀ½°ú °°½À´Ï´Ù: {{{#!vim c void error(int status, int ecode, const char *fmt, ...); }}} ÀÌ ÇÔ¼ö´Â ecode°¡ 0ÀÌ ¾Æ´Ñ °æ¿ì, strerror(ecode) °ªÀ» Ãâ·ÂÇÏ°í, fmt¿Í "..."À¸·Î Àü´ÞµÈ printf() styleÀÇ ¿¡·¯ ¸Þ½ÃÁöµµ Ãâ·ÂÇÑ ´ÙÀ½, status°¡ 0ÀÌ ¾Æ´Ñ °æ¿ì, exit(status)¸¦ È£ÃâÇÕ´Ï´Ù. ÇÔ¼ö Á¤ÀÇ´Â ´ÙÀ½°ú °°½À´Ï´Ù. {{{#!vim c 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); } }}} ´ÙÀ½°ú °°ÀÌ ¾µ ¼ö ÀÖ½À´Ï´Ù. {{{#!vim c #include #include ... 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()¸¦ Á¤ÀÇÇÒ ÇÊ¿ä¾øÀÌ ¹Ù·Î ¾µ ¼ö ÀÖ½À´Ï´Ù. (Ãâ·Â ÇüÅ´ ¾à°£ ´Ù¸¦ ¼ö ÀÖ½À´Ï´Ù¸¸, ÀÎÀÚ 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À̶õ°Ô ¾ø¾ú½À´Ï´Ù. ÀÎÀÚ°¡ ¸î°³ÀÌ°í, ¾î¶² ŸÀÔÀ̳Ŀ¡ »ó°ü¾øÀÌ ´Ü¼øÈ÷ ÇÔ¼ö°¡ ÀÖ°í, ¸®ÅÏ Å¸ÀÔÀÌ ¹¹´Ù. Á¤µµ¸¸ ¾Ë·Á ÁáÁÒ. ¿¹¸¦ µé¸é ´ÙÀ½°ú °°½À´Ï´Ù: {{{#!vim c double bar(); double bar(a, f, ch) int a; float f; char ch; { ... } }}} ÀÌ·± ½ÄÀ¸·Î ÇÔ¼ö¸¦ ¼±¾ðÇÏ°Ô µÇ¸é, ÄÄÆÄÀÏ·¯°¡ ÇÔ¼öÀÇ Á¤ÀǸ¦ º¸±â Àü¿¡´Â ÀÌ ÇÔ¼ö¿¡ Àü´ÞµÇ´Â ÀÎÀÚÀÇ Å¸ÀÔÀÌ ¹ºÁö ¾Ë ¼ö ¾ø½À´Ï´Ù. ¸¸¾à ÄÄÆÄÀÏ·¯°¡ bar()ÀÇ Á¤ÀǸ¦ º¸±â Àü¿¡ ´ÙÀ½°ú °°Àº Äڵ带 ÄÄÆÄÀÏÇØ¾ß ÇÑ´Ù°í °¡Á¤ÇØ º¸±â ¹Ù¶ø´Ï´Ù: {{{#!vim c 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ÀÌ ÀÖÀ¸´Ï, ÄÄÆÄÀÏ·¯°¡ ÇÔ¼ö È£ÃâÀ» Çϱâ Àü¿¡ ÇÔ¼öÀÇ ÀÎÀÚ °¹¼ö¿Í ŸÀÔÀ» ¸ðµÎ ¾Ë ¼ö ÀÖ½À´Ï´Ù. {{{#!vim c double bar(int a, float f, char ch); }}} µû¶ó¼­ ´õ ÀÌ»ó ÀÌ·¯ÇÑ º¯È¯ÀÌ ÇÊ¿ä¾ø°Ô µÇ¾úÁö¸¸, Çϳª ¿¹¿Ü°¡ Àִµ¥, ¹Ù·Î °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. °¡º¯ ÀÎÀÚ´Â ½ÇÁ¦·Î ¾î¶°ÇÑ Å¸ÀÔÀÌ ¸î°³°¡ µé¾î¿Ã Áö ¾Ë ¼ö ¾ø±â ¶§¹®¿¡, ÀÌ·¯ÇÑ º¯È¯ÀÌ °è¼Ó ¼öÇàµË´Ï´Ù. µû¶ó¼­ va_arg()·Î ÀÌ·¯ÇÑ Å¸ÀÔÀ» ¹ÞÀ»·Á¸é ÀÌ integral conversionÀ» ¹Ì¸® »ý°¢ÇØ µÎ¾î¾ß ÇÕ´Ï´Ù. ¿¹¸¦ µé¾î ¹®ÀÚ Çϳª¾¿ ¹Þ¾Æ¼­ Ãâ·ÂÇÏ´Â ÇÔ¼ö¸¦ ¸¸µé¾î º¸°Ú½À´Ï´Ù: {{{#!vim c 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"¸¦ ¾¹´Ï´Ù. ¾Æ·¡ ¿¹ Âü°í: {{{#!vim c 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À» Ãâ·ÂÇÏ´Â ºÎºÐÀº ´ÙÀ½°ú °°Àº Äڵ带 Æ÷ÇÔÇÕ´Ï´Ù: {{{#!vim c value = (float) va_arg(argptr, double); }}} ¶ÇÇÑ scanf ÄÚµå ¾È¿¡¼­ floatÀ» Ãâ·ÂÇÏ´Â ºÎºÐÀº ´ÙÀ½°ú °°Àº Äڵ带 Æ÷ÇÔÇÕ´Ï´Ù: {{{#!vim c ptr = va_arg(argptr, float *); }}} ÀÌ Á¤µµ¸é °¡º¯ ÀÎÀÚ¸¦ ó¸®ÇÏ´Â ¹æ¹ýÀº ¿Ïº®È÷! ÀÍÈ÷¼ÌÀ» °ÍÀÔ´Ï´Ù. ±×·³ ´ÙÀ½ ±âȸ¿¡... ³¡ -- [cinsk] ---- * TODO: Function prototypeÀÌ ANSI C¿¡¼­ ¼Ò°³µÈ °Í ¸Â³ª? * TODO: Integral PromotionÀ̶ó°í Çߴµ¥, ¿©±â¿¡ float, doubleÀÌ Æ÷ÇԵǴ °ÍÀÌ È®½ÇÇÑ°¡? ÀÌ°Å ¾Ë¾Æº¸°í ±Û °íÄ¥ °Í.. -- [cinsk]. ÇÔ¼ö ¼±¾ð(Á¤ÀÇ°¡ ¾Æ´Ñ)ÀÇ °æ¿ì¿¡´Â ±× Àü¿¡µµ ÀÖ¾ú´ø °Í °°½À´Ï´Ù. [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__¸¦ ½áÁÖ¸é ±× ÀÚ¸®¿¡ È®ÀåµË´Ï´Ù. ¿¹¸¦ µé¸é, ´ÙÀ½°ú °°½À´Ï´Ù: {{{#!vim c #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()ÀÇ Á¤ÀÇ°¡ ³ª°©´Ï´Ù: {{{#!vim c #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_()ÀÇ Á¤ÀÇ°¡ ³ª°©´Ï´Ù: {{{#!vim c #include #include #include 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(); } }}} ¿¹¸¦ µé¾î ´ÙÀ½ ÇÔ¼ö¸¦ »ý°¢ÇØ º¾½Ã´Ù: {{{#!vim c void set_age(int age) { ASSERT(age > MIN_AGE, "age should be larger than %d.", MIN_AGE); /* ... */ } }}} MIN_AGE´Â 10À¸·Î Á¤ÀÇµÈ ¸ÅÅ©·ÎÀÌ°í, »ç¿ëÀÚ°¡ set_age(3)À» È£ÃâÇß´Ù¸é, ´ÙÀ½°ú °°Àº ASSERT''''''ionÀÌ ¹ß»ýÇÕ´Ï´Ù: {{{#!vim nosyntax 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] ---- CategoryDevelopment