Uz saturu

PHP un 64 biti

  • 2009.03.04. 19:38
  • Techy

Es, šķiet, pirmo reizi mūžā šodien saskāros ar problēmu, kuras sakne ir tanī, ka 32bit sistēmas un 64bit sistēmas ir ne pārāk viegli savietojamas.

Eksistē maģiska funkcija, kā unpack(). Konkrētajā gadījumā man no četriem secīgiem baitiem nepieciešams “izpakot” 32 bitu naturālu skaitli big endian baitu secībā. Nekādu problēmu. Neskatoties ne uz ko, tas vienmēr ir izdevies bez problēmām. Šodien, uz kādas 64 bitu sistēmas radās nepieciešamība palaist attiecīgo skriptu nevis zem PHP4, kā līdz šim, bet nu jau zem PHP5 (uz 32bit PHP5 problēmu nav). Un tad nu sākās.

list(,$command_id) =  unpack('N', \
    chr(0x80) . chr(0x00) . chr(0x00) . chr(0x09)); 
# Iegūstam -2147483639 

Tas nekas, ka reāli tas ir negatīvs skaitlis, neskatoties uz unpack norādīto informāciju. Sekojošais kods visu noliek savās vietās un iegūstam pozitīvu skaitli:

$command_id = hexdec(dechex($command_id)); 
# Iegūstam 2147483657 

Taču, uz 64bit PHP5 man šāda operācija pēkšņi sāka izsniegt skaitli 1.8446744071562E+19. Neiedziļinoties detaļās – kāpēc tā, sapratu, ka esmu nepareizi darījis. Tā vietā, lai atrisinātu problēmu ar pirmo atrasto metodi, man vajadzēja to saprast līdz saknei un risināt ar pirmo pareizo. Un tā būtu:

$command_id &= 0xffffffff;

Šis atrisina problēmu uz 64bit sistēmām, un neko nesalauž uz 32bit. Kā jau minēju, uz tās pašas kastes PHP4 uzvedās korekti.

Komentāri (6)

  1. Laiks:
    1. Taai @ 2009.03.04. 19:47, teica:
    Komentārs:

    Bet uzmanies un ņem vērā, ka dechex un hexdec funkcijām ir skaitļa limits – 4294967295 !

  2. Laiks:
    2. binary @ 2009.03.04. 21:56, teica:
    Komentārs:

    Taai, droši zini, ka 4294967295? PHP nesupporto unsigned integerus.

  3. Laiks:
    3. binary @ 2009.03.04. 21:58, teica:
    Komentārs:

    brr… tikko pamēģināju uz 32bit windas paskatīties, ko PHP teiks par echo 4294967295-1, echo 4294967295+1, … works like a charm

  4. Laiks:
    4. binary @ 2009.03.04. 22:02, teica:
    Komentārs:

    nevermind. pieleca viss.

  5. Laiks:
    5. bubu @ 2009.03.04. 22:35, teica:
    Komentārs:

    Problēma ir src/ext/standard/pack.c failā. Tur jāizmet ārā 790 rinda. Un arī 793. rinda, jo “V” arī ir unsigned. Un jāpielabo 788. rindu, lai “L” arī neuzstāda issigned mainīgo, jo “L” arī ir unsigned.
    unsigned short’iem gan tur par brīnumu source viss ir korekti.

    Tur vispār viss ir dīvaini. Izrādās “i” un “I” nebūs 8 baiti uz x86-64, jo tur tiek lietots sizeof(int) izmērs – un tas arī x86-64 ir 4 baiti. Diezgan dīvaini. Jo kautkas cits tas ir tikai DOS’ā (2 baiti) vai kautkādās embedded sistēmās, kur diez vai php ir vajadzīgs. Tāda tipa kā sizeof(long) vai sizeof(void*), kuri tiešām atšķirtos starp x86 un x86-64, tur nemaz nav.

    Dīvains tas php ir… Tādā ziņā pitonā ir daudz konsistentāk šitā pakošana un atpakošana saistībā ar C tipiem (int, long, ..).

  6. Laiks:
    6. noisex @ 2009.03.05. 23:31, teica:
    Komentārs:

    uz tas sistemas, kur izmantoju unpack/ord/hexdec utt kombinacijas stav uz 32bit os..nevaru notestet. bet nu prikola pec varetu pamegjinat.

Ierakstīt savu sakāmo


XHTML: Tu vari izmantot šos tagus (un to atribūtus): <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Moderācija: Daži vārdi var gadīties, ka ir iz melnās listes (viagra and stuff). Tādi komentāri tiek premoderēti, pirms parādās lapā. Ja Tavs komentārs neparādās uzreizi, būs vien jāpagaida, līdz es jamo izlasīšu.