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.
- 1567 megtekintés
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).
- A hozzászóláshoz be kell jelentkezni
off
Ha a code tag-et használod, megmarad a formázás, és könnyebben olvasható a példakód.
/off
- A hozzászóláshoz be kell jelentkezni
1.
C89 fordító nem köteles olyan integer konstanst elfogadni, ami
long unsigned
-be nem fér bele.
C99 fordító nem köteles olyen integer konstanst elfogadni, ami
long long unsigned
-be nem fér bele.
Bármelyik felismerheti valamilyen extended integer type-ként értelmezhető konstansként (pl. C89 esetén
long long
), 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
long unsigned
-odba nem fér bele a konstans.
Ilyen konstanst C99 módban minden további nélkül leírhatsz (érdemes azért az
LLU
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>
#include
-olása után a konstanst kifejezésként hordozhatóan (legalábbis SUSv2 platformok számára hordozhatóan) előállíthatod így:
uint64_t magic
= (uint64_t)0x01234567lu << 32 | (uint64_t)0x89ABCDEFlu;
2.
Ilyet szerintem ne írj le többet (hordozhatónak szánt kódban):
*(char *) &n
ahol
n
típusa
int
. Ha
char
valójában
signed char
, simán signed overflow-hoz vezethet, az meg undefined behavior. Alapvetően nem mentség, hogy előtte
n = 1;
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
int
-ben padding bitek legyenek, amelyeknek akármi is lehet az értéke. Ha nagyon muszáj, akkor
unsigned char *
-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
ntohl()
és az
ntohs()
. 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
uint8_t buffer[8]
-ad van, amit véletlenül egy
uint64_t
-be olvastál be. Ennek megfelelően, SUSv2-re gondolva:
uint64_t ntohu64(uint64_t netu64)
{
uint8_t *n = (uint8_t *)&netu64;
return
(uint64_t)n[0] << 56
| (uint64_t)n[1] << 48
| (uint64_t)n[2] << 40
| (uint64_t)n[3] << 32
| (uint64_t)n[4] << 24
| (uint64_t)n[5] << 16
| (uint64_t)n[6] << 8
| (uint64_t)n[7];
}
(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
magic
-ban a byte-ok mind páronként különbözők):
ntohu64(magic) == magic
Ha valaki tud pontosítani, ne habozzon!
- A hozzászóláshoz be kell jelentkezni
Köszönöm a kimerítő válaszokat! Ezekből sajnos az is kiderült, hogy mennyire tudatlan vagyok.
- A hozzászóláshoz be kell jelentkezni
Ez sosem szegyen, mint ahogy tanulni sem az.
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni