C dilinde fonksiyon argümanlarının hesaplanma sırası standart tarafından tanımlanmamıştır (C99 dahil öncesi). Argümanlar soldan sağa, sağdan sola veya herhangi bir başka sırada hesaplanabilir (derleyici veya mimari tercihlerine bağlı olarak).
void fn(int a, int b) { /* ... */ } int x = 1; fn(x++, x++); // x++ ve x++ hesaplama sırası tanımlanmış değil!
"C dilinde fonksiyon argümanları hangi sırayla hesaplanır ve kod yazarken buna güvenilebilir mi?"
Yaygın bir hata, argümanların soldan sağa hesaplandığını varsaymaktır (ifadelerle benzerlik sebebiyle). Pratikte her fonksiyon çağrısı, derleyicinin (ve platformun) tercihlerine göre derlenir.
void foo(int a, int b, int c); int x = 1; foo(x++, x++, x++); // sonuç argümanların hesaplanma sırasına bağlıdır
Gerçek cevap: güvenilmez — davranış tanımlanmamıştır!
Hikaye
Çok platformlu bir üründe bir programcı
push(stack, stack->size++, data);yazdı. Çoğu platformda her şey çalıştı, ancak bir platformda yığın boyutu verileri iletmeden önce artırıldı, diğerinde ise sonra. Veriler "kayboldu" veya yanlış adreslendi, hata nadiren ortaya çıktı ve düzeltmesi çok zor oldu.
Hikaye
Bir ağ protokolü kütüphanesinde, bir loglama fonksiyonu, istatistik sayaçlarını artıran ifade argümanlarıyla çağrıldı. İstatistik raporları yanlış şekilde oluşturuldu: farklı istemcilerde sayaç indeksleri farklıydı çünkü beklenmedik sırada gerçekleştiriliyordu.
Hikaye
Donanım kontrol arayüzünde, bir başlatma fonksiyonu, argümanlar içinde artırma ile işaretçiler ve ofsetler geçiriyordu (örneğin
init(ptr++, cnt++);). Bazı işlemcilerde donanım doğru başlatılırken, diğerlerinde hata oluştu; neden donanımda uzun süre aranmıştı, oysa sorun C kodundaki hatalı koddu.