C99'da uzun uzun

Jan 10 2021

C99 standardında tanıttılar long long. Bunun amacı ne? (Sınırlı) C programlama deneyimimde, yalnızca her biri 4 baytlık bir int ve 8 bayt uzunluğunda gördüm. Örneğin, Derleyici Gezgini'nden:

Eğer longzaten 8o zaman, neden başka eklemek gerekir long longtürü? Bu derleyiciye / mimariye ne yapar?

Yanıtlar

6 chux-ReinstateMonica Jan 10 2021 at 05:36

Uzun zaten 8 ise, neden başka bir uzun uzun tip eklemek gerekiyor? Bu derleyiciye / mimariye ne yapar?

"Eğer uzun zaten 8 ise" her zaman doğru değildir, çünkü 32-bit longve int32 veya 16 bitlere dayanan çok sayıda kod vardır .

long64-bit olarak zorunlu kılmak kod tabanlarını kırabilir. Bu büyük bir endişe kaynağıdır.


Yine longde 32 bit kalmayı (ve hayır long long) gerektirmesi , standart 64 bitlik tamsayılara erişim sağlamaz, dolayısıyla bunun mantığı bir mantıktır long long.

İzin long32 bit veya 64-bit (veya diğerleri) ya da geçiş imkanı verir.

longGibi çeşitli işlevler geçer / geri döner fseek(), ftell(). longBüyük dosya desteği için 32 bitten fazla olmanın avantajını yaşarlar.

Önerilen uygulama daha geniş bir alanı teşvik eder long: "Uygulama bunu gerekli kılacak kadar büyük nesneleri desteklemedikçe, kullanılan türler için kullanılan size_tve ptrdiff_tbundan daha büyük bir tamsayı dönüştürme sıralamasına sahip olmamalıdır signed long int." Bu, 32 biti aşan bellek boyutları ile ilgilidir.


Belki gelecekte bir uygulama int/long/long long/intmax_t32/64/128/256 bit olarak kullanabilir .

IAC, ben türleri genişliği sabit bkz intN_tüzerinde popülaritesi artan longve long long. Ben sabit genişlikli tip veya kullanma eğiliminde bool, ( unsigned) char, int/ unsigned, size_t( u) intmax_tve izni signed char, ( unsigned) short, ( unsigned) long, ( unsigned) long longözel durumlar için.

4 dbush Jan 10 2021 at 05:26

C standardı yalnızca bir int(gevşek bir şekilde) 2 bayt, a long4 bayt ve a long long8 bayt olabilir.

Aslında, MSVC 4 bayta sahip longolmasına rağmen hala 4 bayt kullanır int.

3 NateEldredge Jan 10 2021 at 05:38

Sadece ilgili şartı intve longo zaman ve şimdi, yani inten az 16 bit olmalıdır ve longen az 32 bit olmalıdır. 16 ve 32 bit sistemlerin her ikisi de 32 bit olma eğilimindeydi longve 64 bit makineler 1990'ların sonlarında çok daha az yaygındı. Bu nedenle, C99'dan önce, programcılar 64 bitlik bir tamsayı türünün mevcut olmasına taşınabilir bir şekilde güvenemezlerdi. Bu sorun, long longen az 64 bit olması gereken ürünün tanıtılmasıyla çözüldü . (Zaten GCC ve belki de diğer derleyiciler tarafından bir uzantı olarak sağlandığına inanıyorum).

Bugünlerde 64 bitlik sistemlerin çoğu (ama hepsi değil) 64 bit kullanıyor longve long longdaha büyük yapmak için uğraşmıyor , bu nedenle 64 bit de ve bir bakıma gereksiz. Bunlar muhtemelen aşina olduğunuz sistemlerdir, ancak dışarıdaki her şeyi temsil etmiyorlar.

2 PeterCordes Jan 10 2021 at 10:29

C tipi genişlik gereksinimlerinin nasıl çalıştığı konusunda çok büyük bir yanlış varsayımda bulunduğunuzu fark etmemişsinizdir: ISO C , izin verilen en küçük büyüklük gibi minimum bir değer aralığı belirlerLONG_MAX ve LONG_MIN(-2147483647, 8 değil, çünkü ISO C kişinin tamamlama ve işaret / büyüklük işaretli tamsayılara izin verir, sadece 2'nin tamamlayıcısına değil.) Gerçek uygulamaların, hedef makinenin verimli bir şekilde yapabileceği bir yazmaç genişliğine veya işlenen boyutuna uyması için daha geniş türlere sahip olmasına izin verilir.

Bu konuda Stack Overflow'da ve başka yerlerde çok şey yazıldı, ben burada tekrar etmeye çalışmayacağım. Ayrıca bakınızhttps://en.cppreference.com/w/c/language/arithmetic_types


Bu da sizi x86-64 System V ABI'deki tip-genişlik seçeneklerine bakma ve diğer C uygulamalarının aynı olduğunu varsayma hatasına götürdü. x86-64, 64 bit tam sayılarla verimli bir şekilde çalışabilen 64 bitlik bir ISA'dır, bu nedenle 64 bit longoldukça mantıklı bir seçimdi.

İ386 gibi 32 bitlik bir makine için aklı başında hiçbir ABI 64 bit kullanmaz longçünkü bu gerekli değildir, yalnızca 32 bittir. 64 bit kullanmak, tek bir kayda sığamayacağı anlamına gelir. 32 bit ARM ile derleyin -m32veya derleyin. Godbolt ayrıca AVR ve MSP430 için GCC'ye sahiptir. Bu 8 bit ve 16 bit makinelerde GCC, ISO C tarafından izin verilen en küçük genişlikleri (2 bayt int, vb.)

1999'da x86-64 bile yoktu. (Alpha gibi birkaç başka 64 bit ISA yaptı). Dolayısıyla, C99 seçimlerini anlamak için 2 ana akım ABI'dan birine bakmak sizi çok uzağa götürmeyecektir.

Elbette C'nin, insanların 64 bit tamsayı matematiğini verimli bir şekilde yapan programlar yazmasına izin vermek için en az 64 bit olması garantili bir türe ihtiyacı vardır.


Ve BTW, x86-64, 32-bit tamsayıları 64-bit kadar verimli, bazen daha verimli bir şekilde yapabilir. Bu nedenle long64 bitlik bir tür yapmak tartışmasız harika değildir. Bazı kodlar, long32 bit olması gereken bir tür istediği için kullanır , ancak daha geniş olmasından fayda sağlamaz. Bu tür bir kod için 64 bit, longönbellek ayak izi / bellek bant genişliğini ve kod boyutunu (REX önekleri) boşa harcar. C99'da ideal seçim olacaktır int_least32_t, ancak bu sinir bozucu derecede uzun yazılır ve nadiren kullanılır.

Ancak OTOH'nin longbazen "en geniş verimli (1-kayıt) tip" olması umulur, ancak böyle bir garanti yoktur ve 32-bit ile Windows x64 gibi LLP64 ABI'ler böyle longdeğildir.

Diğer bir bütün solucan kutusu C99 int_fast32_tve x86-64 System V'nin IMO'su bunu 64-bit tip yapmak için zayıf bir seçimdir. (Ben yarım yazılı cevap Neden uint64_t? Çözümlemek gelmez uint64_t için giderir uint32_fast_t CPP ama uint32_t (x86_64). Daha neredeyse tüm işlemler için yavaştır ... Ben bitirmeli int_fast32_tne için hızlı" sorusunu gündeme getiriyor Amaç "ve birçok uygulamada pek çok durumda umduğunuz şey bu değildir.

Ayrıca bakınız

  • C ++ - en hızlı tam sayı türü?
  • [U] int_fastN_t türleri, x32 ABI ile veya x32 olmadan x86_64 için nasıl tanımlanmalıdır?
  • Neden uint_fast32_t yerine uint32_t tercih edilmeli?
  • X86_64'te çarpma için uint_least16_t neden uint_fast16_t'den daha hızlı?
  • Derleyici optimizasyonlarına "int", "en az" ve "hızlı" sabit olmayan genişlik türleri C / C ++ aracılığıyla izin verilir
old_timer Jan 11 2021 at 06:16

Bazı sınırlamalar vardır, ancak derleyici yazarı standart C değişken türleri (char, short, int, long, long long) için uzunlukları seçmekte özgürdür. Doğal olarak char, bu mimari için bir bayt olacaktır (C derleyicilerinin çoğu 8 bittir). Ve doğal olarak, daha küçük bir şeyin daha büyük bir şeyden daha büyük olması olamaz, uzun bir int'ten daha küçük olamaz. Ama kesinlikle 1999'da x86 16'dan 32 bit'e geçişi gördük ve örneğin int bir dizi araçla 16'dan 32'ye değişti, ancak uzun süre 32 kaldı. Daha sonra 32'den 64 bit'e x86 geçişi oldu ve araca bağlı olarak kullanılabilen tipler vardı yardım etmek.

Sorun bundan çok önce de vardı ve çözüm, türlerin uzunluklarını düzeltmek değildi, bunlar, kurallar dahilinde, boyut bakımından derleyici yazarlarına kalmıştı. Ancak derleyici yazarlarının araç ve hedefle eşleşen bir stdint.h dosyası oluşturması gerekir (stdint.h en azından bir araca ve hedefe özgüdür ve bu araç için araç sürümü ve oluşturma seçenekleri olabilir, vb.). Böylece, örneğin, uint32_t her zaman 32 bittir. Bazı yazarlar stdint.h dosyasında bunu bir int'e, bazıları da uzun, vb. Dönüştürecek. C dili değişken türleri, dil başına char, short, int, vb. İle sınırlı kalır (uint32_t bir değişken türü değildir ve stdint.h aracılığıyla bir değişken türüne dönüştürülür). Bu çözüm / geçici çözüm, her şeyin delirmesini engellemenin ve dili canlı tutmanın bir yoluydu.

Yazarlar, örneğin, GPR'lerin 16 bit olup olmadığını, int'in 16 bit olup olmadığını ve 32 bit ise 32 bit vb. Olup olmadığını, ancak biraz özgürlükleri olduğunu seçeceklerdir.

Evet, bu özellikle, belirli bir hedef için herhangi iki aracın (örneğin, bunu okuduğunuz bilgisayar) int ve özellikle long için aynı tanımları kullandığını ve eğer için kod yazmak istediğinizi varsaymak için hiçbir neden olmadığı anlamına gelir. Bu araçları (bu platformu destekleyen) geçebilen bu platform daha sonra int, long vb. değil stdint.h türlerini kullanın ... Kesinlikle platformları geçiyorsanız, bir msp430 mcu, bir kol mcu, bir kol linux makinesi aynı "araç zinciri" için bile türlerin (örneğin gnu gcc ve binutils) int ve long için aynı tanımlara sahip olmadığı x86 tabanlı bir makine, char ve short 8 ve 16 bit olma eğilimindedir, int ve long en çok değişme eğilimindedir, bazen birbirleriyle aynı boyutta, bazen farklıdır, ancak asıl mesele varsayılmamaktadır.

Bir derleyici sürümü / hedef / komut satırı seçenekleri için boyutları tespit etmek ya da sorunları daha sonra en aza indirmek için sadece stdint rotasına gitmek önemsizdir.