C standardı, derleyicilere optimizasyonları gerçekleştirmek için çok fazla serbestlik sağlar. Başlatılmamış belleğin rastgele bir bit modeline ayarlandığı ve tüm işlemlerin yazıldıkları sırada gerçekleştirildiği saf bir program modelini varsayarsanız, bu optimizasyonların sonuçları şaşırtıcı olabilir.
Not: Aşağıdaki örnekler sadece x
adresi hiçbir zaman alınmadığı için geçerlidir , bu yüzden "kayıt benzeri" dir. x
Tuzak temsillerinin türünün olması durumunda da geçerli olacaktır ; Bu, imzasız türler için nadiren söz konusudur (en az bir bit depolama alanını “boşa harcamayı” gerektirir ve belgelenmelidir) ve bunun için imkansızdır unsigned char
. Eğer x
(2 - imzalanmış türü oldu ve ardından uygulama, bir sayı arasında değil bit modelini tanımlayabilir n-1 1) ve 2 N-1 -1 tuzak temsili olarak. Jens Gustedt'in cevabına bakın .
Derleyiciler değişkenlere yazmaç atamaya çalışır, çünkü yazmaçlar bellekten daha hızlıdır. Program, işlemcinin yazmaçlarına göre daha fazla değişken kullanabileceğinden, derleyiciler, farklı zamanlarda aynı kaydı kullanan farklı değişkenlere yol açan kayıt tahsisi gerçekleştirir. Program parçasını düşünün
unsigned x, y, z;
y = 0;
z = 4;
x = - x;
y = y + z;
x = y + 1;
3. satır değerlendirildiğinde, x
henüz başlatılmamıştır, bu nedenle (derleyicinin nedenleri) 3. satır, derleyicinin anlayacak kadar akıllı olmadığı diğer koşullar nedeniyle gerçekleşemeyen bir tür tesadüf olmalıdır. Yana z
hattı 4 sonra kullanılmaz ve x
hat 5 önce kullanılmaz, aynı kayıt iki değişken için kullanılabilir. Dolayısıyla bu küçük program, kayıtlar üzerinde aşağıdaki işlemlere göre derlenmiştir:
r1 = 0;
r0 = 4;
r0 = - r0;
r1 += r0;
r0 = r1;
Nihai değeri x
, nihai değeridir r0
ve nihai değeri y
, nihai değeridir r1
. Bu değerler x = -3 ve y = -4'tür ve x
uygun şekilde başlatılmış olsaydı olacağı gibi 5 ve 4 değildir .
Daha ayrıntılı bir örnek için aşağıdaki kod parçasını göz önünde bulundurun:
unsigned i, x;
for (i = 0; i < 10; i++) {
x = (condition() ? some_value() : -x);
}
Derleyicinin condition
hiçbir yan etkisi olmadığını algıladığını varsayalım . Değişiklik condition
yapmadığından x
, derleyici döngü boyunca ilk çalıştırmanın x
henüz başlatılmadığı için erişilemeyeceğini bilir . Bu nedenle, döngü gövdesinin ilk çalıştırılması x = some_value()
koşulu test etmeye gerek yoktur. Derleyici bu kodu sizin yazmışsınız gibi derleyebilir
unsigned i, x;
i = 0;
x = some_value();
for (i = 1; i < 10; i++) {
x = (condition() ? some_value() : -x);
}
Bu derleyici iç modellenmiş olabilir yolu bağlı herhangi bir değer olduğunu dikkate almaktır x
sahiptir uygun olduğu herhangi bir değer uzun olarak x
başlatılmamış olması. İlklendirilmemiş bir değişkenin davranışı tanımsız olduğundan, değişkenin sadece tanımlanmamış bir değere sahip olması yerine, derleyicinin uygun olan değerler arasındaki herhangi bir özel matematiksel ilişkiyi takip etmesi gerekmez. Böylece derleyici yukarıdaki kodu şu şekilde analiz edebilir:
- ilk döngü yinelemesi sırasında,
x
zaman -x
değerlendirildiğinde başlatılmamış olur.
-x
tanımsız bir davranışa sahiptir, dolayısıyla değeri uygun olanıdır.
- Optimizasyon kuralı geçerlidir, bu nedenle bu kod basitleştirilebilir .
condition ? value : value
condition; value
Sorunuzdaki kodla karşılaşıldığında, aynı derleyici x = - x
, değerlendirildiğinde değerinin uygun olanı -x
olduğunu analiz eder . Böylece atama optimize edilebilir.
Yukarıda açıklandığı gibi davranan bir derleyici örneği aramadım, ancak bu iyi derleyicilerin yapmaya çalıştığı optimizasyon türleridir. Biriyle karşılaşmak beni şaşırtmaz. İşte programınızın çöktüğü daha az makul bir derleyici örneği. (Programınızı bir tür gelişmiş hata ayıklama modunda derlerseniz bu mantıksız olmayabilir.)
Bu varsayımsal derleyici, farklı bir bellek sayfasındaki her değişkeni eşler ve sayfa özniteliklerini ayarlar, böylece başlatılmamış bir değişkenden okuma, bir hata ayıklayıcıyı çağıran bir işlemci tuzağına neden olur. Bir değişkene yapılan herhangi bir atama, önce onun bellek sayfasının normal şekilde eşleştirilmesini sağlar. Bu derleyici herhangi bir gelişmiş optimizasyon gerçekleştirmeye çalışmaz - başlatılmamış değişkenler gibi hataları kolayca bulmayı amaçlayan bir hata ayıklama modundadır. Ne zaman x = - x
değerlendirilir, sağ taraftaki bir tuzak neden olur ve ayıklayıcı kadar ateşler.