Tarihsel olarak C dilinde lvalue ve rvalue arasındaki fark, atama operatörünün hangi ifadelere uygulanabileceğini belirlemenin temelini oluşturmuştur. Lvalue (sol değer), belirli bir bellek konumunu işgal eden ve adres alma işlemi (&) uygulanan bir nesneyi belirtir. Rvalue (sağ değer) ise belirli bir adresi olmayan geçici bir değerdir. Bu ayrım, atamanın, fonksiyona argüman aktarımının ve derleyici optimizasyonlarının nasıl çalıştığını anlamak için önemlidir.
Sorun, yalnızca lvalue üzerinde izin verilen işlemleri (örneğin, atama) rvalue üzerinde gerçekleştirmeye çalıştığınızda ve tersine ortaya çıkar. Bu, derleme hatalarına veya yürütme aşamasında belirsiz hatalara yol açabilir.
Çözüm, lvalue ve rvalue kullanım bağlamlarını net bir şekilde anlamaktır. Örnek:
int x = 5; int y; y = x; // x — lvalue ve rvalue, y — lvalue y = x + 1; // x + 1 — rvalue (adres alınamaz) // &x — geçerli, &(x + 1) — hata
Temel özellikler:
Herhangi bir ifadenin adresinin alınması mümkün müdür, örneğin (x + y) ifadesinden?
Hayır, yalnızca lvalue’nin adresi vardır. Örneğin, (x + y) ifadesi — rvalue’dır.
int z = 3, y = 7; int *p = &(z + y); // Derleme hatası
Bir sabite (örneğin, 5 = x) değer atamaya çalışıldığında ne olur?
Derleme hatası oluşur, çünkü literatür 5 — rvalue’dir ve lvalue olarak kullanılamaz.
5 = x; // Hata: sol operand lvalue değil
Fonksiyon lvalue dönebilir mi?
Sıradan bir fonksiyon rvalue döner, ancak bir referans döndürüldüğünde (örneğin, C++’ta) bu lvalue olur. C’de yalnızca rvalue döndürülmesine izin verilir.
int foo() { int x = 5; return x; } // rvalue döner
Programcı geçici sonuç ifadesinin (a + b) adresini almaya çalıştı:
int *p = &(a + b);
Artılar:
Eksiler:
Programcı lvalue ve rvalue’yi bilinçli bir şekilde ayırır. Sadece sözdizimi ve anlamsal açıdan izin verilen yerlerde değerleri kullanır:
int x = 7; int *p = &x; // geçerli
Artılar:
Eksiler: