SORU
12 Kasım 2010, Cuma


C : int64_t vs vs long int long long int

Yaşadığım bazı tuhaf davranışlar kullanırken C tip özellikleri ve daralmış benim sorunum bu garip küçük bir sorun için vereceğim bir ton açıklama beri istemiyorum bırakın her şeyi açmak için yanlış.

Böyle bir programınız olsun

#include <iostream>
#include <cstdint>

template <typename T>
bool is_int64() { return false; }

template <>
bool is_int64<int64_t>() { return true; }

int main()
{
 std::cout << "int:\t" << is_int64<int>() << std::endl;
 std::cout << "int64_t:\t" << is_int64<int64_t>() << std::endl;
 std::cout << "long int:\t" << is_int64<long int>() << std::endl;
 std::cout << "long long int:\t" << is_int64<long long int>() << std::endl;

 return 0;
}

32-bit GCC (32 - ve 64-bit MSVC ile) derleme, program çıktısı:

int:           0
int64_t:       1
long int:      0
long long int: 1

Ancak, program bir 64-bit kaynaklanan derlenir çıktı GCC:

int:           0
int64_t:       1
long int:      1
long long int: 0

Bu merak, yana long long int bir imzalı 64-bit tamsayı ve, tüm niyet ve amaçlar, aynı long int int64_t türleri, mantıki olarak, int64_t, long int long long int olurdu eşdeğer türleri - Kurul tarafından oluşturulan kullanırken bu tür ile aynı. stdint.h bak bir neden söyledi:

# if __WORDSIZE == 64
typedef long int  int64_t;
# else
__extension__
typedef long long int  int64_t;
# endif

Bir 64-bit derleme int64_t long int long long int (belli ki).

Bu durumu düzeltmek için oldukça kolaydır:

#if defined(__GNUC__) && (__WORDSIZE == 64)
template <>
bool is_int64<long long int>() { return true; }
#endif

Ama bu korkunç hackish ve iyi (Madde, uint64_t, vb gerçek fonksiyonlar) ölçeklendirme değil.Benim sorum ise şu:Bir şekilde bir long long int de long int ** 27, sadece bu derleyici söylemek var mı?


İlk düşüncelerim bu mümkün değil, C/C tür tanımları çalışma biçimi nedeniyle. Orada olmayan bir şekilde belirtmek eşdeğerlik türü temel veri türleri için derleyici, derleyici beri bu işi (ve izin bu kırabilecek bir çok şey) ve typedef sadece gider bir şekilde.

Ben de çok endişe ile bir cevap, başka bir deyişle bir super-duper kenar durumda değil ki ben şüpheli olur hiç bakım hakkında ne örnekler değil korkunç yapmacık (demek bu olmalı topluluk wiki?).


Ekleyin: Gibi kolay bir örnek yerine kısmi şablon ihtisas kullanıyorum nedeni:

void go(int64_t) { }

int main()
{
    long long int x = 2;
    go(x);
    return 0;
}

long long int int64_t örtük olarak dönüştürülebilir olduğundan örnek hala oluşturacağını açıkladı.


Ekleyin: Tek cevap şu ana kadar eğer bir türü 64-bit olup olmadığını bilmek istiyorum varsayar. Değer verdiğim düşünerek insanları yanıltmak istemedim ve muhtemelen bu sorun ortaya çıkmaktadır burada daha fazla örnek vermiş.

template <typename T>
struct some_type_trait : boost::false_type { };

template <>
struct some_type_trait<int64_t> : boost::true_type { };

Bu örnekte, some_type_trait<long int>* *35, ama some_type_trait<long long int> olmayacak bir olacak. Bu C duygusu 's tür fikir, değil arzu edilir. yapar

Başka bir örnek same_type gibi bir niteleyici C 0x Kavram olarak kullanımı oldukça yaygın olan) kullanarak

template <typename T>
void same_type(T, T) { }

void foo()
{
    long int x;
    long long int y;
    same_type(x, y);
}

Örnek C (doğru) türlerinden farklı olduğunu görür beri derlemek için başarısız olur. g gibi bir hata ile derlemek başarısız olur: eşleşen bir işlev çağrısı same_type(long int&, long long int&).

Anlıyorum ki bir kez daha vurgulamak istiyorumnedenbu oluyor, ama beni her yerde kodu tekrar etmeye gücü olmayan bir çözüm arıyorum.

CEVAP
12 Kasım 2010, Cuma


64-bit için böyle bir şey görmeye gerek yok. Ortak int32_t 32-bit platformlar düşünün. typedefher iki long ama belli ki sadece bir kişi olarak int gibi ya. ed olabilir int long elbette farklı türleri vardır.

Zor değil 32-bit sistemlerde int == int32_t == long yapar çözüm yok bunu görmek için. Aynı nedenle, 64-bit sistemlerde long == int64_t == long long yapmak için bir yol yok.

Eğer olsaydı, olası sonuçları foo(int), foo(long) ve aynı aşırı yük için iki tanım olurdu foo(long long) aniden aşırı yüklendi? kod bu oldukça acı verici olurdu!

Doğru çözüm şablon kodunuzu genellikle bu tür özellikleri üzerinde hassas bir tür, ama güvenerek edilmemelidir. same_type tüm mantık hala belirli durumlar için iyi olabilir:

long foo(long x);
std::tr1::disable_if(same_type(int64_t, long), int64_t)::type foo(int64_t);

I. e., 53* *aşırı olduğunda tanımlı değiltam olarakfoo(long) aynı.

[Düzenle] C ile 11, biz şimdi bunu yazmak için standart bir yol var:

long foo(long x);
std::enable_if<!std::is_same<int64_t, long>::value, int64_t>::type foo(int64_t);

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Commander Chalkboard

    Commander Ch

    20 Ocak 2014
  • Dylan Brenan

    Dylan Brenan

    22 Aralık 2009
  • hytchme

    hytchme

    9 Mart 2014