Portál AbcLinuxu, 12. května 2025 05:06
Mam takovy maly vetsi problem s Cckem a kdevelop. Pisu drobnej programek pracujici s BMP souborem. Data se nactou do nejakyho bufferu, zavola se funkce nize a ta mi z ukazatele na buffer udela ukazatel na strukturu hlavicek BMP a ty pak porovnava. Tak jak je kod napsany nize, tak take funguje - temer jak bych si pral. Struktura paradne sedi s datama ze souboru. K totalnimu blahu by mi stacilo malo: chtel bych odkomentovat ty dva radky a smazat to '+2'. Jenze tu je kamen urazu - Nefunguje to! Ten prvni short se mi v debuggeru zobrazi spravne, ale data za nim od bfSize dal jsou posunuta ne o dva, ale o ctyri bajty! Teorii Ccka a kompilatoru gcc jsem nikdy obzvlaste nestudoval, ale pod linuxem uz jsem napsal nejakych par fungujicich daemonu, slozitejsich databazovych aplikaci a hacku vseho moznyho... Ale toto vidim poprve. Netusite nahodou nekdo cimto?
typedef struct { // short bfType; long bfSize; long bfReserved; long bfOffBits; long biSize; long biWidth; long biHeight; short biPlanes; short biBitCount; } bmp_headers; int getCentralPoint(char *buffer, long buf_len, long xres, long yres, long x, long y) { char *poi; poi=buffer; bmp_headers *header; header=(bmp_headers*)(buffer+2); // if(header->bfType!=0x4d42) return -1; if(buf_len!=header->bfSize) return -1; if(header->bfOffBits!=54) return -1; if(header->biWidth!=xres) return -1; if(header->biHeight!=yres) return -1; if(header->biBitCount!=24) return -1; ...
sizeof
short na tvem systemu? Proste misto 2 pouzij sizeof(short)
.
CFLAGS="-O3 -march=athlon-4 -pipe -fomit-frame-pointer" CHOST="i686-pc-linux-gnu"
Ale dylka shortu to primo neni to, co me trapi. Jako hexa cislo mi ho to ukazuje skutecne dva bajty. Horsi je, ze ta druha promenna je po odkomentovani zarovnana od ctvrtyho bajtu a ne od druhyho (resp tedy jeji offset od pocatku struktury je +4 a ne +2). A pritom, kdyz ji vynecham, tak ty dalsi dva shorty tam dal jsou spravne.
No, short by snad mel byt vsude 2B a skutecne mi to tak pise. Stejne jako long by mel bejt 4B.
Můžete, prosím, poskytnout referenci na místo v normě jazyka C, kde se tohle píše? Já mám třeba sizeof(long)
rovno osmi…
Jak to je ti povi uryvek z C Programming Language od K&R:
The intent is that short
and long
should provide different lengths of integers where practical; int
will normally be the natural size for a particular machine. short
is often 16 bits long, and int
either 16 or 32 bits. Each compiler is free to choose appropriate sizes for its own hardware, subject only to the restriction that shorts
and ints
are at least 16 bits, longs
are at least 32 bits, and short/code> is no longer than
int
, which is no longer than long
No, short by snad mel byt vsude 2B a skutecne mi to tak pise. Stejne jako long by mel bejt 4B.A na to jste prisel kde? Je to totiz pekna blbost. Jedine, co je zaruceno je, ze pro rozsahy plati short <= int <= long <= long long. Jak vidite o rozsahu v bytech tam nic neni, a proto klidne vsechny muzou byt stejne velke, treba 32bitu a je to spravne.
a rekl bych ze za to mohou posledni verze GCC, ktere pocitaji uz jen s 32bitovymi adresovacimi prostory a zarovnavaji vse na 32 bit
Ne. Mohou za to nezodpovědní programátoři, kteří na základě své zkušenosti z jedné konkrétní verze jednoho konkrétního prohlížeče (s jedním konkrétním nastavením) na jedné platformě neoprávněně usuzují, že přesně stejně se musejí chovat všechny prohlížeče na všech platformách.
#pragma pack(push,1)
struct....
#pragma pack(pop)
Specifikace jazyka neříká nic o tom, jak budou jednotlivé položky struktury zarovnány v paměti. To, co požadujete, se dá u některých překladačů vynutit speciální direktivou, ale obecně to zařídit nelze. Musíte si uvědomit, že existují i platformy, kde procesor neumí číst 32-bitové slovo z adresy, která není dělitelná čtyřmi (a i tam, kde to jde, je to často pomalejší).
Navíc si zaděláváte na problémy s kompatibilitou už tím, že položky deklarujete jako short
a long
, což jsou datové typy, o jejichž velikosti nevíte obecně vůbec nic kromě toho, že sizeof(long) >= sizeof(short)
. Takže ta vaše ukázka kódu je odstrašujícím příkladem toho, co nazývám empirickým programováním - zkusil jste to přeložit na jednom počítači jedním překladačem s jednou variantou parametrů a fungovalo to, takže usuzujete, že to musí fungovat všude.
Ale pri te prilezitosti by me tedy zajimalo, jak by se to dalo co nejvic koser napsat univerzalneji. Rad se necemu novemu priucim... Preci jenom 64b pocitacu asi mozna ubyvat nebude...
riešenie oboch je rovnaké:
header->bfxxx = read_int16 (buffer); header->bfyyy = read_int64 (buffer);
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.