عملگر کاما

در زبان برنامه‌نویسی سی و سی++، عملگر کاما که توسط علامت , نشان داده می‌شود، یک عملگر دودویی است که اولین عملوندش را ارزیابی می‌کند، اما نتیجه آن را باطل کرده و سپس دومین عملوندش را ارزیابی می‌کند و سپس مقدار (و نوع) عملگر دومش را برمی‌گرداند.
استفاده از نشانه کاما به عنوان یک عملگر ، متمایز از به کار بردن آن در فراخوانی و تعریف توابع، اعلان متغیرها، اعلان نوع شمارشی، و ساختارهای مشابه است. در این گونه موارد، کاما به عنوان یک جداساز عمل می‌کند و نه به عنوان یک عملگر .
نحو
عملگر کاما عبارات (که دارای مقدار هستند) را از هم جدا می‌کند. این کار مشابه عملگر سمی‌کالن است که دستورها را خاتمه می‌دهد. دنباله‌ای از عبارات که در داخل پرانتز قرار گرفته‌اند، مشابه دنباله‌ای دستورها است که در داخل آکولاد قرار دارند. برای مثال، (a, b, c) دنباله‌ای از عبارات است که توسط کاما جدا شده‌اند و در آن تنها آخرین عبارت که c است ارزیابی می‌شود، در حالی که {a; b; c; دنباله‌ای از دستورها است که توسط سمی‌کالن جدا شده‌اند و به هیچ مقداری ارزیابی نمی‌شود. توجه کنید که کاما می‌تواند در بین دو عبارت قرار گیرد. کاما عبارات را از یکدیگر جدا می‌کند . این برخلاف عملکرد سمی‌کالن است که در پایان دستورها قرار می‌گیرد و به دستورها خاتمه می‌دهد.
در بین عملگرهای سی، عملگر کاما پایین‌ترین اولویت را دارد و به عنوان یک نقطه توالی عمل می‌کند. اگر کاماها و سمی‌کالن‌ها با هم ترکیب شوند، سمی‌کالن‌ها اولویت پایین‌ترین نسبت به کاماها خواهند داشت. چرا که سمی‌کالن‌ها دستورها را از هم جدا می‌کنند، اما کاماها خود بخشی از دستور هستند و در داخل آن قرار دارند. عبارت a, b; c, d به صورت (a, b); (c, d) گروه‌بندی می‌شود، چرا که آنها دو دستور مجزا هستند.
مثال‌ها
در مثال‌های زیر، تفاوت رفتار بین خطوط دوم و سوم به این خاطر است که عملگر کاما اولویت کمتری نسبت به عملگر انتساب (=) دارد.
// Examples: Descriptions: Values after line is evaluated:
int a=1, b=2, c=3, i=0; // comma acts as separator in this line, not as an operator … a=1, b=2, c=3, i=0
i = (a, b); // stores b into i … a=1, b=2, c=3, i=2
i = a, b; // stores a into i. Equivalent to (i = a), b; … a=1, b=2, c=3, i=1
i = (a += 2, a + b); // increases a by 2, then stores a+b = 3+2 into i … a=3, b=2, c=3, i=5
i = a += 2, a + b; // increases a by 2, then stores a into i. Equivalent to (i = (a += 2)), a + b; … a=5, b=2, c=3, i=5
i = a, b, c; // stores a into i … a=5, b=2, c=3, i=5
i = (a, b, c); // stores c into i … a=5, b=2, c=3, i=3
در خط اول، کاما به عنوان یک جدا ساز عمل می‌کند و نه به عنوان یک عملگر. در خط دوم، عملگر کاما مقدار a را باطل کرده و b را برمی‌گرداند و سپس b به متغیر i منتسب می‌شود.
توجه کنید که از کاما نمی‌توان برای اندیس‌گذاری آرایه چندبعدی استفاده کرد. Ai, j به صورت Aj ارزیابی می‌شود و i در آن نابود می‌شود. شکل درست اعلان یک آرایه دو بعدی Aij است.
موارد استفاده
حلقه for
یکی از مواردی که عملگر کاما زیاد استفاده می‌شود، انتساب مرکب و همزمان چند متغیر بدون استفاده از یک بلاک کد است. خصوصا در حلقه for می‌توان از چند شمارنده حلقه استفاده کرد و همزمان آنها را با هم مقداردهی کرد یا آنها را با هم افزایش داد. در مثال زیر ترتیب مقداردهی اولیه به شمارنده‌های حلقه مهم است:
void rev(char *s, size_t len)
char *first;
for (first = s, s += len - 1; s>= first; --s)
putchar(*s);
عملگر کاما در برخی موارد می‌تواند مترادف با عملگر سمی‌کالن استفاده شود، خصوصا وقتی که دستورات مورد نظر مشابه قسمت گام افزایشی حلقه for باشد:
++p, ++q;
++p; ++q;
شرط‌ها
از کاما می‌توان در شرط حلقه‌های if, while, do while یا for برای انجام محاسبات کمکی استفاده کرد. مثلا می‌توان تابعی را فراخوانی کرده و مقدار برگشتی آن را در یک متغیر ذخیره کرد.
if (y = f(x), y> x) {
… // statements involving x and y
مقدار برگشتی پیچیده
از کاما می‌توان در دستور return برای مقداردهی به یک متغیر سراسری یا یک پارامتر خروجی (که توسط روش فراخوانی با ارجاع به تابع ارسال شده) استفاده کرد. به این ترتیب، این تصور به وجود می‌آید که عمل انتساب بخشی از دستور return است. به جای انجام این کار در بلاکی که آخرین دستور آن return است. برای مثال، برای مقدار دهی یک متغیر سراسری می‌توان چنین عمل کرد:
if (failure)
return (errno = EINVAL, -1);
نمونه گویاتر کد بالا به شکل زیر است:
if (failure) {
errno = EINVAL;
return -1;
پرهیز از یک بلاک
برای اختصار در نوشتن، می‌توان به جای نوشتن یک بلاک و آکولادهای آن، از عملگر کاما به شکل زیر استفاده کرد:
if (x == 1) y = 2, z = 3;
if (x == 1)
y = 2, z = 3;
در عوض:
if (x == 1) {y = 2; z = 3;
if (x == 1) {
y = 2; z = 3;