Fórumok
Hi!
Az alábbi kódban:
static inline uint64_t be64_to_cpu(uint64_t *y)
{
int n = 1 ;
if(*(char *) &n == 1) // True if the cpu is little endian.
{
*y = (*y>>56) |
((*y<<40) & 0x00FF000000000000) |
((*y<<24) & 0x0000FF0000000000) |
((*y<<8) & 0x000000FF00000000) |
((*y>>8) & 0x00000000FF000000) |
((*y>>24) & 0x0000000000FF0000) |
((*y>>40) & 0x000000000000FF00) |
(*y<<56);
}
return *y;
}
az "((*y<<40) & 0x00FF000000000000) |" sorra a gcc a következő hibát adja:
integer constant is too large for 'long' type
Nem igazán tudom, hogy miért nem jó ez egy "unsigned long" típusú változónak.
Hozzászólások
Nem igazán tudom, hogy miért nem jó ez egy "unsigned long" típusú változónak.
64bites rendszer alatt (ha az inttypes.h-t inkludolod), akkor teljesen jo.
32bites rendszer alatt valoban warning jon, ekkor tegye'l egy LL vegzodest a szamok (konstansok) utan: 0x00FF000000000000LL. So"t, az ULL me'g jobb (hangsulyozod hogy unsigned). talan a legjobb az, ha ezt me'g (maga't a konstanst) uint64_t-re kasztolod me'g a & mu"velet elo"tt. ha nagyon peda'ns akarsz lenni (hasznalsz -Wall, -ansi, ... kapcsolokat), akkor hogy ne nyu"gjon a fordito semmit, forditsd -Wno-long-long-gal (a fenti pendans kapcsolok utan add a't a cmdline-ba).
off
Ha a code tag-et használod, megmarad a formázás, és könnyebben olvasható a példakód.
/off
1.
C89 fordító nem köteles olyan integer konstanst elfogadni, ami
-be nem fér bele.
C99 fordító nem köteles olyen integer konstanst elfogadni, ami
-be nem fér bele.
Bármelyik felismerheti valamilyen extended integer type-ként értelmezhető konstansként (pl. C89 esetén
), de nem köteles.
A jelen C++ szabvány a C89-re épül.
Valószínűleg C89 módot vagy C++-t használsz, és a
-odba nem fér bele a konstans.
Ilyen konstanst C99 módban minden további nélkül leírhatsz (érdemes azért az
szuffixet odaírni, hogy garantáltan előjel nélküli legyen). Puszta C89-ben (hordozható kódban) egyáltalán nem írhatod le, még kifejezésként sem (nem biztos, hogy létezik bármilyen egész típus, amelyben elfér). C++-ban, úgy vélem, szintén ez a helyzet.
Ha C89-ben dolgozol, és a platformod támogatja a Single Unix Specification Version 2-t, akkor az <inttypes.h>
-olása után a konstanst kifejezésként hordozhatóan (legalábbis SUSv2 platformok számára hordozhatóan) előállíthatod így:
2.
Ilyet szerintem ne írj le többet (hordozhatónak szánt kódban):
ahol
típusa
. Ha
valójában
, simán signed overflow-hoz vezethet, az meg undefined behavior. Alapvetően nem mentség, hogy előtte
szerepelt; most így nekifutásból, pongyolán tárgyalva, pusztán C89-ben maradva, nem tudom általában véve kizárni, hogy az
-ben padding bitek legyenek, amelyeknek akármi is lehet az értéke. Ha nagyon muszáj, akkor
-on keresztül érd el, az mindig definiált (object representation) hozzáférés, de az érték akármi is lehet. (A kettes komplemens ábrázolás sem garantált, például.)
Lehet, hogy ahol használtad, ott megbízható; nekem mindenesetre bántja a szememet.
3.
A konkrét célra -- vagyis network byte order-ből (= big endian-ból, MSB-ből) host byte order-be konvertálásra -- ugye 32 bites és 16 bites előjel nélküli egészeknél elérhető az
és az
. 64 bitesekhez tudtommal nincs ilyen hordozható függvény, ezért valóban szükséges lehet írni egyet. Ekkor viszont a bemenő paramétert ne a shift operátorokkal érd el, hiszen azok a host byte order szerint dolgoznak, neked pedig csak egy network byte order szerint kitöltött
-ad van, amit véletlenül egy
-be olvastál be. Ennek megfelelően, SUSv2-re gondolva:
(A szignatúrán még lehet reszelni, próbáltam a meglévők mintájára.)
Ha az elején ellenőrizni akarod, hogy kell-e egyáltalán használnod, akkor (kihasználva, hogy a fenti
-ban a byte-ok mind páronként különbözők):
Ha valaki tud pontosítani, ne habozzon!
Köszönöm a kimerítő válaszokat! Ezekből sajnos az is kiderült, hogy mennyire tudatlan vagyok.
Ez sosem szegyen, mint ahogy tanulni sem az.
--