| کتابخانه استاندارد سی |
| --- |
| * انواع داده
* طبقه‌بندی کاراکترها
* رشته‌ها
* ریاضیات
* ورودی/خروجی فایل
* تاریخ/زمان
* بومی‌سازی
* اختصاص حافظه
* کنترل روند
* سیگنال‌ها
* نشانه‌های جایگزین

**سرآیندهای متفرقه**:* `<assert.h>`
* `<Errno.h>`
* `<setjmp.h>`
* `<Stdarg.h>`
 |
| * ن
* ب
* و
 |

**stdarg.h** یک فایل سرایند در کتابخانه استاندارد سی است که به توابع اجازه می‌دهد تا آرگومان‌هایی به تعداد نامعین و دلخواه دریافت کنند. در حالت کلی، در زبان برنامه‌نویسی سی، تعداد پارامترهای یک تابع صریحاً در هنگام اعلان تابع مشخص می‌شود و در هنگام فراخوانی تابع باید دقیقاً به تعداد پارامترها، آرگومان به تابع ارسال شود. اما در برخی مواقع نیاز است تا یک تابع تعداد نامشخصی آرگومان دریافت کند. به کمک امکاناتی که توسط این فایل سرایند محیا شده، می‌توان چنین توابعی را اعلان کرد. از جمله پرکاربردترین توابع از این نوع، تابع printf است. اصطلاحاً به این گونه توابع، **توابع متغیر** گفته می‌شود.

اعلان
-----

توابع متغیر توابعی هستند که آرگومان‌هایی به تعداد دلخواه و نامشخص دریافت کنند. در هنگام اعلان این توابع، آخرین پارامتر تابع باید به صورت سه نقطه تعریف شود. مانند زیر:

```
 int check(int a, double b, ...);

```

حداقل یکی از پارمترها باید دارای یک نام مشخص باشد. بنابراین چنین اعلانی نادرست است:

```
 char \*wrong(...);

```

این کار در زبان سی جایز نیست. هرچند که چنین اعلانی در زبان سی++ جایز است، اما خیلی مفید نیستند. در زبان سی، قبل از سه نقطه حتماً باید یک کاما قرار داشته باشد. در سی++ این کاما اختیاری است.

دسترسی به آرگومان‌ها
--------------------

برای دسترسی به آرگومان‌های بی‌نام، باید متغیری از نوع va\_list در داخل تابع اعلان شود. سپس ماکروی va\_start با دو آرگومان فراخوانی می‌شود، اولی همان متغیر نوع va\_list است که اعلان شده، دومی هم نام آخرین پارامتر دارای نام در اعلان تابع است. بعد از انجام این کار، با هر بار فراخوانی یک ماکرو به نام va\_arg، آرگومان بعدی بدست می‌آید. این ماکرو هم دو آرگومان دریافت می‌کند: اولین آرگومان همان متغیر نوع va\_list است که قبلاً اعلان شده، دومی هم نوع آرگومانی که به تابع ارسال شده را مشخص می‌کند. در نهایت، قبل از اینکه اجرای تابع خاتمه یابد و تابع برگردد، باید ماکرو va\_end فراخوانی شود.

هیچ راهی برای تعیین کردن تعداد یا نوع آرگومان‌هایی که به تابع ارسال می‌شوند تعیین نشده است. تابع باید به طریقی بداند که چه تعداد آرگومان و از چه نوعی دریافت کرده است. راه‌حل‌های رایج برای انجام این کار عبارتند از:

* همانند توابع printf و scanf از یک رشته کنترلی برای تعیین تعداد و نوع آرگومان‌ها مشخص شود. در این رشته تعدادی علائم خاص تعبیه شود که هر علامت نشانگر یک نوع داده باشد. تعداد آرگومان‌ها هم از جمع کردن این علائم بدست می‌آید.
* در انتهای لیست آرگومان‌ها یک نشانه قرار داده شود.
* یک آرگومان مخصوص برای تعیین تعداد آرگومان‌ها در نظر گرفته شود. در هنگام فراخوانی تابع، برنامه‌نویس باید مشخص کند که می‌خواهد تابع را با چند آرگومان فراخوانی کند.

مثال
----

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

/\* print all non-negative args one at a time;
 all args are assumed to be of int type \*/
void printargs(int arg1, ...)
{
 va\_list ap;
 int i;

 va\_start(ap, arg1); 
 for (i = arg1; i>= 0; i = va\_arg(ap, int))
 printf("%d ", i);
 va\_end(ap);
 putchar('\n');
}

int main(void)
{
 printargs(5, 2, 14, 84, 97, 15, 24, 48, -1);
 printargs(84, 51, -1);
 printargs(-1);
 printargs(1, -1);
 return 0;
}

```

خروجی:

```
5 2 14 84 97 15 24 48
84 51
```

```
1
```

منابع
-----

مشارکت‌کنندگان ویکی‌پدیا. «stdarg.h». در *دانشنامهٔ ویکی‌پدیای انگلیسی*، بازبینی‌شده در ۲۱ ژوئیه ۲۰۱۳.