2010-10-25 3 views
13

Używam czasami arytmetyki 64-bitowej w bibliotece C++ o otwartym kodzie źródłowym. Odkryłem, że long long służy mi całkiem nieźle. Nawet 10-letnie urządzenie solaris może je skompilować. I działa bez zakłócania z #defines w systemie Windows.Jak wykonać przenośną 64-bitową arytmetykę, bez ostrzeżeń kompilatora

Problem polega na tym, że dostaję skargi od moich użytkowników, ponieważ kompilują się z ustawieniami GCC - a GCC nalega na ostrzeżenia, że ​​long long nie jest częścią standardu C++. Jest to prawdopodobnie słuszne, ale nie jestem zbyt zainteresowany standardem C++ per se, po prostu chcę, aby mój kod działał na tak wielu kompilatorach, jak to tylko możliwe.

Więc moje pytanie jest dwojaki:

  • może ktoś wymienić rzeczywiste C++ kompilatory, które nie obsługują 64 bit długo Longa?
  • Czy istnieje sposób, aby skompilować GCC 64-bitową arytmetykę (na platformie 32-bitowej) bez ostrzeżeń kompilatora? (stdint.h nie pomaga, ponieważ zależy również od long long)

P.S.

Jeśli istnieją platformy, na których długie odcinki stają się 128-bitowe lub większe, jest to interesujące, ale nie stanowi to dla mnie problemu.

+5

Użycie polecenia -pedantic to dobry sposób na uzyskanie * nie * pracy i uniemożliwienie korzystania z większości bibliotek stron trzecich bez ważnego powodu. To jest to, co mówi na blaszce - bezsensowna skarga, ale nie sądzę, że mówienie swoim użytkownikom, aby przestali być tak głupi, przydałoby by się wam ich !? – Clifford

+11

@Clifford: '-pedantic' jest po to, aby pomóc ci napisać kod, który będzie łatwy do przeniesienia do innych kompilatorów w przyszłości. Jeśli nie martwisz się o to, nie musisz go używać, ale w końcu będziesz osobą, która pisze te biblioteki osób trzecich, które (a) produkują dziwne ostrzeżenia, i (b) całkiem możliwe, że nie ". t działa na niektórych kompilatorach. To prawda, że ​​'long long' nie jest najprawdopodobniej prawdziwym problemem, ale kiedyś pracowałem na przenośnym produkcie i kilkakrotnie naprawialiśmy rzeczy z chłopców z Windowsa, które faktycznie nie działały na niektórych naszych platformach (i gcc -pedantic powiedziałbym im tak). –

+0

... o dziwo, kiedy programiści Linuksa pracowali nad przenośnym komponentem produktu, ich kod był mniej prawdopodobny, aby nie przejść testów na innych platformach. –

Odpowiedz

15

Gdy biblioteka jest dostarczany jako źródła, jedną z opcji jest zapewnienie „portowania” nagłówek, w którym jest odpowiedzialność swoich użytkowników do zapewnienia typ 64 bitowy (chcesz podać nazwę) . W związku z tym ich obowiązkiem jest radzenie sobie z ostrzeżeniami każdego kompilatora, że ​​ich wybór typu prowokuje, albo ich unikać, tłumić lub ignorować.

Podejrzewam, że to jest to, co nazywacie "zakłócaniem z #defines", ale nie sądzę, że jest w tym zbyt wiele zła. Możesz podać wersję domyślną, która bezpośrednio używa long long i będzie działać na twoim 10-letnim pudełku Solaris, a także na Windowsie, aby większość użytkowników nigdy nie musiała zbliżać się do konfigurowalnej przez użytkownika części twojej biblioteki.

Następnie dla użytkowników pedantycznych można podać wersję GCC, która obejmuje <sys/types.h> i używa int64_t zamiast long long. Nie powoduje to żadnego ostrzeżenia dla mnie z g++ -pedantic.Możesz nawet zrobić to w domyślnej wersji, rozpoznając GCC, który na pewno miesza się z #defines, ale znowu nie w sposób, który jest niezwykły dla produktu wieloplatformowego.

Jeśli twoja biblioteka jest również dostarczana jako pliki binarne dla niektórych platform, to oczywiście musisz zdecydować, jaki będzie typ 64-bitowy. Jeśli pojawia się również w interfejsie biblioteki (a więc w pliku nagłówkowym), to musisz wybrać taki, który nie spowoduje żadnych ostrzeżeń z rozsądnymi opcjami kompilatora. Myślę, że -pedantic jest rozsądną opcją kompilatora, i najwyraźniej także twoi użytkownicy, więc znowu to jest int64_t na GCC.

+0

+1, myślę, że int64_t jest tutaj najlepszym rozwiązaniem. – rmeador

+0

Mam plik config.h.W pewnym momencie używałem już 'int64_t' (od stdint.h), ale porzuciłem go na długo, ponieważ ten drugi był znacznie szerszy obsługiwany. Interesujące jest to, że 'int64_t' (od stdint.h) działa, nawet jeśli jest typedef dla' long long' (w moim systemie). Bije mnie, ale dzięki za ustawienie mnie na właściwym torze. –

+0

@jdv: To dlatego, że Void wspomina: nagłówek GCC używa '__extension__', w'/usr/include/sys/_types.h' na moim komputerze. –

12

W GCC użyj opcji kompilatora -Wno-long-long, aby wyłączyć to ostrzeżenie.

Można również użyć -std=C++0x, ale prawdopodobnie jeszcze bardziej zmniejszy przenośność.

+0

Naprawdę mam nadzieję, że można to naprawić bez przełącznika wiersza poleceń, ale dzięki, w każdym razie. –

4

Możesz wyciszyć ostrzeżenie za pomocą -Wno-long-long (upewnij się, że pojawia się po -pedantic). 64-bitowe liczby całkowite są wymagane przez C99 i myślę, że również C++ 0x, więc kompilatory, które ich nie mają, stają się rzadkością w dzisiejszych czasach.

+0

Nie sądzę, że obsługa C99 wymaga obsługi "long long', ale myślę, że jest wymagana przez C++ 0x. – Brian

+0

Jestem w 100% pewien, że jest w C99, ale jestem prawie pewien, że nie ma go w C++ 98. (W owym czasie była to wielka sprawa, ponieważ Microsoft zmusił komitet do zaakceptowania "sizeof (size_t)> sizeof (long)' "jako legalnej opcji ABI, która obiecana przez C89 nigdy by się nie wydarzyła.) – zwol

+0

Będę kontynuował argumentację chodzi o C99. –

0

Można zastąpić korzystanie z long long z jedną z wielu bibliotek C++ bigint. Jestem pewien, że niektórzy z nich unikną tego błędu kompilatora. Osobiście wolałbym trzymać się błędu.

4

Można również pominąć ostrzeżenie za pomocą "__extension__" funkcji GCC, np

// No '-pedantic' warning/error. 
__extension__ long long foo = 2; 

// Exhibits '-pedantic' warning/error. 
long long bar = 3 

i opracowanie:

$ g++ -pedantic -fsyntax-only foo.cpp 
foo.cpp:5: error: ISO C++ 1998 does not support 'long long' 

Zauważ, że tylko ostatni wykorzystanie long long wywołany błąd -pedantic od nr __extension__ został dodany. Niezależnie od tego skorzystam z @Steve Jessop's suggestion z używania int64_t.

1

Jeśli masz impuls w systemie to katalog, można powiedzieć

#include "boost/cstdint.hpp" 
boost::int64_t my_64_bit_number; 

Jeśli jest w systemie to katalog, ostrzeżenia są automatycznie zmniejszane.

+1

Nie będę używać tej sugestii, ponieważ nie używam jeszcze wzmocnienia. Ale dzięki. –