C'nin diğer bazı dillerle karşılaştırıldığında ilginç bir özelliği, veri türlerinin çoğunun mutlak terimlerle belirtilmek yerine hedef mimarinin kelime boyutuna dayanmasıdır. Bu, dilin belirli türlerle zorluk yaşayabilecek makinelerde kod yazmak için kullanılmasına izin verirken , farklı mimarilerde tutarlı bir şekilde çalışacak kod tasarlamayı çok zorlaştırır. Kodu düşünün:
uint16_t ffff16 = 0xFFFF;
int64_t who_knows = ffff16 * ffff16;
int
16 bit (hala birçok küçük mikrodenetleyici için geçerli) olan bir mimaride bu kod, iyi tanımlanmış davranışlar kullanarak 1 değerini atayacaktır. int
64 bit olan makinelerde , yine iyi tanımlanmış davranışlar kullanarak 4294836225 değerini atayacaktır. int
32 bit olan makinelerde , muhtemelen -131071 değeri atayacaktır (bunun Uygulama Tanımlı mı yoksa Tanımlanmamış Davranış mı olacağını bilmiyorum). Kod, nominal olarak "sabit boyutlu" türler olarak kabul edilenler dışında hiçbir şey kullanmasa da, standart bugün kullanılan iki farklı derleyicinin iki farklı sonuç vermesini ve bugün birçok popüler derleyicinin üçte birini vermesini gerektirecektir.
Bu belirli örnek, gerçek dünya kodunda iki 16 bit değerin ürününü doğrudan 64 bit değere atamasını beklemeyeceğim, ancak üç yollu tamsayıyı göstermek için kısa bir örnek olarak seçildi. promosyonlar sözde sabit boyutlu işaretsiz türlerle etkileşime girebilir. İmzasız tiplerde matematiğin matematiksel tamsayı aritmetiği kurallarına göre gerçekleştirilmesinin gerekli olduğu bazı gerçek dünya durumları, modüler aritmetik kurallarına göre yapılması gerektiği ve bazıları gerçekten yapmadığı bazı gerçek dünya durumları vardır. önemli değil. Sağlama toplamı gibi şeyler için birçok gerçek dünya kodu uint32_t
aritmetik sarma moduna 2³² ve keyfi performansa dayanmaya dayanıruint16_t
en az doğru olan aritmetik ve get sonuçları, 65536 doğru mod olarak tanımlanmıştır (Tanımsız Davranışı tetiklemenin aksine).
Bu durum açıkça istenmeyen görünse bile (ve 64 bit işleme birçok amaç için norm haline geldikçe daha fazla olacak), gözlemlediğim şeyden C standartları komitesi, bazı önemli üretimde zaten kullanılan dil özelliklerini tanıtmayı tercih ediyor "sıfırdan" icat etmek yerine C dilinin sadece bir türün nasıl saklanacağını değil, aynı zamanda olası tanıtımları içeren senaryolarda nasıl davranması gerektiğini belirtmesine izin verecek dikkate değer uzantılar var mı? Bir derleyici uzantısının bu tür sorunları çözmesinin en az üç yolunu görebiliyorum:
Derleyiciye belirli "temel" tamsayı türlerini belirli boyutlar olmaya zorlama talimatı veren bir yönerge ekleyerek.
Derleyiciye, hedef mimarideki türlerin gerçek boyutlarından bağımsız olarak, makinenin türlerinin belirli boyutlara sahipmiş gibi çeşitli tanıtım senaryolarını değerlendirmesini söyleyen bir yönerge ekleyerek.
Bir eklenmesi; (belirli özellikleri olan bir türü ne olursa olsun, altta yatan bir kelime büyüklüğü, bir mod-65536 sarma cebirsel halkası gibi davranması gerektiği ve diğer türlerdeki örtük olarak dönüştürülebilir olmamalıdır, örneğin declare tipleri bildirimi araçlarını izin vererek
wrap32
bir içinint
bir vermelidir türünün sonucu, 16 bit'ten büyükwrap32
olup olmadığına bakılmaksızın, doğrudan bir aint
eklemek yasadışı olmalıdır (çünkü ikisi de diğerine dönüşemez).wrap32
wrap16
Benim tercihim üçüncü alternatif olurdu, çünkü alışılmadık kelime boyutlarına sahip makinelerin bile değişkenlerin iki boyuttan güçle olduğu gibi "sarmasını" bekleyen çok sayıda kodla çalışmasına izin verecekti; derleyici, türün uygun şekilde davranmasını sağlamak için bit maskeleme talimatları eklemek zorunda kalabilir, ancak kod mod 65536'yı saran bir türe ihtiyaç duyarsa, derleyicinin kaynak kodunu onunla karıştırmaktan ziyade bu tür maskeleme yapması daha iyidir. veya böyle bir maskeleme gereken makinelerde bu kodu kullanamazsınız. Yine de, yukarıdaki araçlardan herhangi biri aracılığıyla veya düşünmediğim bazı yollarla taşınabilir davranış elde edecek ortak uzantılar olup olmadığını merak ediyorum.
Aradığım şeyi netleştirmek için birkaç şey var; en önemlisi:
İstenen anlambilimi sağlamak için kodun yazılabilmesi için birçok yol olsa da (örn. Gerçekleştirilecek makroları tanımlamak, belirli boyuttaki imzasız işlenenler üzerinde açık bir şekilde saran veya olmayan bir sonuç elde etmek için matematik yapmak) veya en azından istenmeyenleri önlemek semantik (örneğin bir tür şartlı tanımlamak
wrap32_t
olmakuint32_t
bir derleyicilerdeuint32_t
terfi olmazdı ve figür daha iyi gerektirir kodu olduğunuwrap32_t
o tip çalıştırmak ve sahte davranış verim için daha terfi ediyorum makinelerde derleme başarısız), gelecekteki dil uzantıları ile en uygun olan kodu yazmanın herhangi bir yolu varsa, bunu kullanmak kendi yaklaşımımı tasarlamaktan daha iyi olurdu.Birçok tamsayı boyutu sorununu çözmek için dilin nasıl genişletilebileceğine dair oldukça sağlam fikirlerim var, kodun farklı kelime boyutlarına sahip makinelerde aynı anlambilimi vermesine izin veriyorum, ancak bunları yazmak için önemli bir zaman harcamamadan önce bu yönde hangi çabaların zaten yapıldığını bilmek.
Hiçbir şekilde C Standartları Komitesi'ni veya ürettikleri işi küçümseme olarak görülmek istemiyorum; Ancak, birkaç yıl içinde "doğal" tanıtım türünün 32 bit olacağı makinelerde ve 64 bit olacağı makinelerde kodun doğru şekilde çalışmasının gerekli olacağını umuyorum. Dile bazı mütevazı uzantılarla (C99 ve C14 arasındaki diğer değişikliklerin çoğundan daha mütevazı) düşünüyorum, sadece 64 bit mimarileri verimli bir şekilde kullanmak için temiz bir yol sağlamak mümkün olmayacak, aynı zamanda pazarlık ile etkileşimi de kolaylaştıracak "olağandışı kelimelik boyutlu" standardı olan 12-bit ile makinelerde mümkün kılar destek [örneğin tarihsel bükülmüş üzerinde geriye sahip olduğunu makineleri char
bir bekler çalışma kodunauint32_t
mod 2³² sarmak için]. Gelecekteki uzantıların alacağı yöne bağlı olarak, bugün yazılan kodun, varsayılan tamsayı türlerinin "beklenen" gibi davrandığı bugünün derleyicilerinde kullanılabilmesini sağlayacak, ancak tamsayıların gelecekteki derleyicilerinde de kullanılabilmesini sağlayacak makrolar tanımlamanın mümkün olmasını beklerdim. türler varsayılan olarak farklı davranır, ancak gerekli davranışları nerede sağlayabilir?
int
, ancak yine de gizlice içeri giriyor. (Yine C standardını anladığımın doğru olduğunu varsayarsak.)
int
daha büyükseuint16_t
, çarpmanın işlenenleri yükseltilecekint
ve çarpma çarpma olarak gerçekleştirilecekint
ve elde edilenint
değerint64_t
, başlatılması için dönüştürülecektirwho_knows
.