Маленький сюрприз при переходе на 64x

Santiago

Новичок
Автор оригинала: Lightning
Посмотрел документацию внимательно. Это не баг :)
ЧТД.

Где в PHP тип long?
int в php это long в zval.

Zend/zend.h
Код:
typedef union _zvalue_value {
	long lval;					/* long value */
	double dval;				/* double value */
	struct {
		char *val;
		int len;
	} str;
	HashTable *ht;				/* hash table value */
	zend_object_value obj;
} zvalue_value;


struct _zval_struct {
	/* Variable information */
	zvalue_value value;		/* value */
	zend_uint refcount;
	zend_uchar type;	/* active type */
	zend_uchar is_ref;
};
long в Си - это signed long int
Так что в php long есть ;)

Автор оригинала: grigori
мне кажется, рабочим может быть вариант
$addr = sprintf('%u',ip2long('255.255.255.0'));
а в комментах в документации стоит написать об этом
Это там и написано.

Автор оригинала: phprus
На сколько я помню, все еще хуже. sizeof дает размер типа не в байтах, а в char'ах, тоесть sizeof(char) по определению равен 1, но никто не гарантирует, что в байтах тип char занимает ровно один байт.
Строго говоря, sizeof возвращает size_t, который может быть определен в stddef. h в зависимости от платформы.
 

phprus

Moderator
Команда форума
Santiago
Я говорил не про то, какой тип возвращает sizeof(), а то, как интерпретировать то число, которое он вернет.
На сколько я помню, по определению 1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long), Но "1" слева - это относительная величина. Стандарт не гарантирует что она равна байту.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
да, эта тема, безусловно, стоит еще нескольких страниц флейма

заодно можно обсудить:
* есть ли жизнь на Марсе и почему в PHP нет unsigned int
* недостатки языков высокого уровня (особенно тех, на которых аффтары не писали)
* жизнь - дерьмо, Tony не удолетворяет всех, а PHP - недо-кроссплатформенный недоязык :)
 

Kelkos

Сам себе программер
Автор оригинала: grigori
да, эта тема, безусловно, стоит еще нескольких страниц флейма

заодно можно обсудить:
* есть ли жизнь на Марсе и почему в PHP нет unsigned int
* недостатки языков высокого уровня (особенно тех, на которых аффтары не писали)
* жизнь - дерьмо, Tony не удолетворяет всех, а PHP - недо-кроссплатформенный недоязык :)
Это чо..
я щас вам ещё дровишек подкину.

Берём и пишем в базу что нам генерит ip2long на 64х битах и получаем.. получаем..
оппа!

PHP:
"Id"	"FIELD_INT"	"FIELD_CHAR"	"FIELD_IP"
1	430669298	"430669298"	"25.171.125.242"
2	2147483647	"3584677056"	"213.169.212.192"   !!!!!!!!!!!!!!!!!!!!!!
3	1166189451	"1166189451"	"69.130.163.139"
4	2147483647	"4053303956"	"241.152.130.148"   !!!!!!!!!!!!!!!!!!!!!!
5	1865563869	"1865563869"	"111.50.62.221"
6	1907029356	"1907029356"	"113.170.245.108"
7	1841336505	"1841336505"	"109.192.144.185"
8	2147483647	"4213704981"	"251.40.9.21"           !!!!!!!!!!!!!!!!!!!!!!
9	2147483647	"3548841896"	"211.135.7.168"       !!!!!!!!!!!!!!!!!!!!!!
10	836528502	"836528502"	"49.220.105.118"
табла:
CREATE TABLE `test` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`FIELD_INT` int(11) NOT NULL DEFAULT '0',
`FIELD_CHAR` varchar(20) NOT NULL DEFAULT '',
`FIELD_IP` varchar(15) NOT NULL DEFAULT '',
PRIMARY KEY (`Id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;


Давайте дальше теорию. Очень интересно.
 

Wicked

Новичок
предлагаю дать таким "дровишкам" название - "адские багрепорты Kelkosа" :)
потому что понять, о чем идет речь, почти не представляется возможным :)

-~{}~ 17.06.09 18:49:

а в чем проблема-то?
`FIELD_INT` int(11) - это ни что иное, как signed integer размером 4 байта с диапазоном -2147483648 ... 2147483647
 

Kelkos

Сам себе программер
Wicked, ээх.. что тут может быть непонятного?

В моём примере в id 2, например.

FIELD_INT не равен FIELD_CHAR

В оба поля я записал результат ip2long (FIELD_IP) на 64 битах.

Т.е.. Скрипты использующие ip2long и запись результата в базу будут плодить неверные значения.
Т.е. становится, что int в php совсем не то, что int в MySQL

так лучше?
 

Lightning

Трудоголик
Kelkos
Давайте дальше теорию. Очень интересно.
Да какая тут теория?

PHP:
<?
    echo decbin( ip2long( '255.255.255.255' ) );
?>
На 32-х битной и на 64-x битной платформе функция работает одинаково!

Т.е. ip2long( '255.255.255.255' ) возвращает значение (в двоичной системе):
11111111 11111111 11111111 11111111

Т.к. в PHP размерность int платформо-зависима (это написано в документации, см. ссылку выше), то на 64-х естественно в памяти будет:
00000000 00000000 00000000 00000000 11111111 11111111 11111111 11111111

Где тут баг?
Ты хочешь чтобы функция возвращала:
10000000 00000000 00000000 00000000 01111111 11111111 11111111 11111111
?
 

Kelkos

Сам себе программер
Lightning, я к тому, что в мануале на главной странице шрифтом 200px и красным цветом надо написать, что int в php на 64хбитах соответствует bigint в MySQL и без пары костылей некоторые функции не будут работать так, как нам хочется.

А также могут глючить сайты при смене платформы и почему и где они могут глючить.

Более, того, при первом открытии мануала надо поставить галочку "да, прочитал, понял, буду знать", а иначе мануал не открыть.

хех.
 

Lightning

Трудоголик
я к тому, что в мануале на главной странице шрифтом 200px и красным цветом надо написать, что int в php на 64хбитах соответствует bigint в MySQL и без пары костылей некоторые функции не будут работать так, как нам хочется.
Ну это уже слишком, ИМХО :)

В мануале написано:
The size of an integer is platform-dependent
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Kelkos
гы, я так однажды на переполнении счетчика int потерял день работы скрипта.
автоинкрементное поле переполнилось и вместо ошибки при добавлении данных mysql переписывал последнюю запись

-~{}~ 17.06.09 18:43:

теперь выставляю в my.cnf
sql_mode=STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: Kelkos
Это чо..
я щас вам ещё дровишек подкину.

Берём и пишем в базу что нам генерит ip2long на 64х битах и получаем.. получаем..
оппа!

PHP:
"Id"	"FIELD_INT"	"FIELD_CHAR"	"FIELD_IP"
1	430669298	"430669298"	"25.171.125.242"
2	2147483647	"3584677056"	"213.169.212.192"   !!!!!!!!!!!!!!!!!!!!!!
3	1166189451	"1166189451"	"69.130.163.139"
4	2147483647	"4053303956"	"241.152.130.148"   !!!!!!!!!!!!!!!!!!!!!!
5	1865563869	"1865563869"	"111.50.62.221"
6	1907029356	"1907029356"	"113.170.245.108"
7	1841336505	"1841336505"	"109.192.144.185"
8	2147483647	"4213704981"	"251.40.9.21"           !!!!!!!!!!!!!!!!!!!!!!
9	2147483647	"3548841896"	"211.135.7.168"       !!!!!!!!!!!!!!!!!!!!!!
10	836528502	"836528502"	"49.220.105.118"
табла:
CREATE TABLE `test` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`FIELD_INT` int(11) NOT NULL DEFAULT '0',
`FIELD_CHAR` varchar(20) NOT NULL DEFAULT '',
`FIELD_IP` varchar(15) NOT NULL DEFAULT '',
PRIMARY KEY (`Id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;


Давайте дальше теорию. Очень интересно.
Это не теория, это практика наступания на мысклеграбли. MySQL по умолчанию обрезает значения, неподходящие под размеры поля, хотя все адекватные СУБД их отвергают. В Postgres'е такой финт ушами, естественно, не пройдёт:
Код:
Welcome to psql 8.3.7, the PostgreSQL interactive terminal.

Type:  \copyright for distribution terms
       \h for help with SQL commands
       \? for help with psql commands
       \g or terminate with semicolon to execute query
       \q to quit

postgres=# create table test (field integer);
CREATE TABLE
postgres=# insert into test values (3584677056);
ERROR:  integer out of range
postgres=#
Собственно, не пройдёт он и в MySQL, если подкрутить какие-то настройки, но сам факт наличия этих настроек кагбэ символизирует.

-~{}~ 17.06.09 23:03:

Автор оригинала: Lightning
Kelkos

Да какая тут теория?

PHP:
<?
    echo decbin( ip2long( '255.255.255.255' ) );
?>
На 32-х битной и на 64-x битной платформе функция работает одинаково!

Т.е. ip2long( '255.255.255.255' ) возвращает значение (в двоичной системе):
11111111 11111111 11111111 11111111

Т.к. в PHP размерность int платформо-зависима (это написано в документации, см. ссылку выше), то на 64-х естественно в памяти будет:
00000000 00000000 00000000 00000000 11111111 11111111 11111111 11111111

Где тут баг?
Ты хочешь чтобы функция возвращала:
10000000 00000000 00000000 00000000 01111111 11111111 11111111 11111111
?
Я не Kelkos, но я хочу, чтобы функция возвращала одинаковые значения на 32-битной и 64-битной платформе. Мне абсолютно похрен, как выглядят битики в памяти, но если на 32-битной я получал -1, то будьте добры вернуть -1 на 64-битной платформе. Либо задокументируйте, что "результат функции зависит от фаз луны, кишок животного и разрядности платформы".

Потому что доказывать что чёрное --- это белое, а в военное время значение -1 может быть равно 4294967295 несколько глупо, не?
 

SiMM

Новичок
> Ты хочешь чтобы функция возвращала: 10000000 00000000 00000000 00000000 01111111 11111111 11111111 11111111
Lightning, справедливости ради замечу, что Вам стоило бы разобраться с дополнительным кодом, потому что это Ваше предложение явно взято с потолка.
 

pilot911

Новичок
Автор оригинала: Kelkos
int в php на 64хбитах соответствует bigint в MySQL
то есть, если скрипт рассчитан на долгую жизнь, придется подобные поля уже сейчас делать bigint ? или я что-то непонимаю ?
 

vovanium

Новичок
придется подобные поля уже сейчас делать bigint ? или я что-то непонимаю ?
Для ip можно юзать mysql'ные функции INET_ATON/NTOA, в мускуле нет проблем с типизацией

-~{}~ 17.06.09 22:50:

Собственно, не пройдёт он и в MySQL, если подкрутить какие-то настройки, но сам факт наличия этих настроек кагбэ символизирует.
Включить STRICT и будет счастье :)
 

Kelkos

Сам себе программер
то есть, если скрипт рассчитан на долгую жизнь, придется подобные поля уже сейчас делать bigint ? или я что-то непонимаю ?
Нет. Немного не так.
Просто надо очень аккуратно обращаться с int и большими значениями, делать "костыли" на некоторые функции в РНР, помнить, что на 32х битах, например, intval('3548841896') == 2147483647 и что MySQL может не понять, что ты ему пытаешься записать в int на 64х.

В общем, заморочки.
 

pilot911

Новичок
Автор оригинала: Kelkos
Нет. Немного не так.
Просто надо очень аккуратно обращаться с int и большими значениями, делать "костыли" на некоторые функции в РНР, помнить, что на 32х битах, например, intval('3548841896') == 2147483647 и что MySQL может не понять, что ты ему пытаешься записать в int на 64х.

В общем, заморочки.
intval одна из самых используемых функций

как с ней быть, можно пример ?
 

Santiago

Новичок
Автор оригинала: Sad Spirit
Я не Kelkos, но я хочу, чтобы функция возвращала одинаковые значения на 32-битной и 64-битной платформе. Мне абсолютно похрен, как выглядят битики в памяти, но если на 32-битной я получал -1, то будьте добры вернуть -1 на 64-битной платформе.
Пошли по второму кругу.
Для этого в документации и указано, что если нужно получить одинаковое значение в попугаях, то преобразуйте в строку. Если не нужно в попугаях, берите int (signed long int). А он платформо-зависим. И с точки зрения двочиного представления -1 на 32х битха и 64х битах будут разными числами. И не будут соотвествовать одному типу данных.

Либо задокументируйте, что "результат функции зависит от фаз луны, кишок животного и разрядности платформы".
Оно и задокументировано, в разделе описания типов. Логично, что посмотрев на тип значения, которое возвращает функция, затем нужно посмотреть его описание. А там черным по белому сказано "the size of an integer is platform-dependent".
 

Kelkos

Сам себе программер
ntval одна из самых используемых функций. как с ней быть, можно пример ?
Если ты не используешь числа int более 2147483647 и не используешь функции типа ip2long (и обратную), crc32 (и какие там ещё?), то тебе пофиг на разрядность.

А вот в противном случае начнутся баги/глюки и надо быть очень внимательным и понимать, что, куда и откуда.
 

pilot911

Новичок
Автор оригинала: Kelkos
Если ты не используешь числа int более 2147483647 и не используешь функции типа ip2long (и обратную), crc32 (и какие там ещё?), то тебе пофиг на разрядность.

А вот в противном случае начнутся баги/глюки и надо быть очень внимательным и понимать, что, куда и откуда.
ясно, спасибо :)
 

Lightning

Трудоголик
Автор оригинала: Sad Spirit
Я не Kelkos, но я хочу, чтобы функция возвращала одинаковые значения на 32-битной и 64-битной платформе.
Еще раз: функция возвращает одинаковые значение на 32-битной и 64-битной платформе.

PHP:
<?
    echo decbin( ip2long( '255.255.255.255' ) );
?>
Разве этот код выдает разные значения на 32-битной и 64-битной платформе?

-~{}~ 18.06.09 14:13:

Lightning, справедливости ради замечу, что Вам стоило бы разобраться с дополнительным кодом, потому что это Ваше предложение явно взято с потолка.
Да, тут я ошибся. -1 на 64-х битах будет выглядеть как 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111. Но сути это не меняет.
 
Сверху