Как было прежде отмечено, доступ к информации обычно делается по-байтовый.
Соответственно, каждый тип данных занимает тот или иной набор байт.
Байт может принимать до 2 в 8 (8 бит, каждый принимает одно из двух значений) степени значений - 256.
Основные типы данных:
1. символ.
такой тип есть в любом "нормальном" языке, к коим не относятся языки в роде php, потому что php относится к языкам "сделаю все за вас".
именно поэтому php-программисты избавлены от работы со строками на уровне символов. и именно поэтому некоторые из них даже не знает о том, что это за тип "символ", а что за тип "строка".
такая работа со строками на уровне символов возможна между тем даже в php.
символ занимает один байт и по сути своей является числом от 0 до 255. в пхп чтобы получить это число, можно воспользоваться функцией ord.
Примечание:
кодировки Unicode (многобайтные) занимают больше одного байта. в этих случаях просто не стоит забывать, что символ это то же самое число. просто для двухбайтовой кодировки оно уже будет не от 0 до 255, а от 0 до 65535.
2. числовой.
в php размер числового типа зависит от разрядности шины. обычно это 32 - у персональных компутеров, и 64 - у крутых (или может даже не очень крутых) серверов.
не надо пугаться и путать - 32 и 64 битов. размер в байтах будет соответственно - 4 и 8.
рассмотрим пример, когда максимальный размер числа задан 32 битами. это 2 в 32 степени и это примерно 10 в 12.
таким образом числовым типом можно представить число до 11 знаков. тогда как представление его в качестве строки будет занимать 11 байт (против 4 числом).
с другой стороны число от 1 до 9 все так же занимает 4 байта, а символом его можно представить. и займет оно тогда всего 1 байт.
Однако, если требуется произвести над числом математическую операцию, оно будет приведено к числовому типу в любом случае.
Примечание:
в языке С есть несколько разновидностей числового типа
small int - двухбайтовый int
int - четырехбайтовый
long int - размер зависит от разрядности, как в php. этот тип наиболее похож на числовой тип, используемый в php.
long long int - восьмибайтовый
плюс каждый из этих типов может быть unsigned (беззнаковый). это свойство многим знакомо по языку sql.
по умолчанию каждый из этих типов имеет знак, а значит один бит требуется на его определение.
это значит, что тип small int знаковый имеет диапазон не (0; 65535), а (-32768; 32767). тогда как беззнаковый (0; 65535).
в php числовой тип является знаковым.
3. тип с плавающей точкой (десятичная дробь)
есть две основные разновидности - float и double.
в C float - 4 байта,
double - 8 байт.
в php float и double являются синонимомами и эквивалентны типу double в С.
любое число с плавающей точкой представляется в памяти как комбинация мантиссы (m) и показателя степени ®. соответствующее им число находится по формуле
n = m * r^10;
m всегда число от 0 до 1.
r - целое.
этот формат хранения позволяет хранить в 8 байтах числа до 10 в 308 степени. однако имеет свой недостаток:
такие числа имеют погрешность, поскольку m часто имеет недостаточную точность для представления необходимой мантиссы.
иначе говоря с типом float/double возможен такой случай
Заметьте, что числа нарочно берутся как float/double (свидетельствует десятичная точка при записи).
3.0 * 15.0 = 45.000000003;
это связано как раз с тем, что число 45 не представимо в таком формате, а ближайшим к нему является эта штука с кучей нулей.
приведенные числа, как бы то ни было, взяты из головы.
4. булев тип.
все просто - всего два значения. но минимальная единица памяти - байт, поэтому boolean занимает целый байт, несмотря на то, что хватило бы и бита.
5. массив
массив - это набор переменных, следующих подряд в памяти (как сказано в первой части - каждый байт имеет свой адрес).
и как очевидно - адрес аппаратный, и не имеет никакого отношения к ключам ассоциативного массива.
примечание:
тип "строка" это частный случай массива. это массив, каждый элемент которого является символом.
не стоит правда пускаться с этого момента с легкостью переводить строки в массивы. массив в пхп это достаточно навороченная прослойка над обычным массивом, и как следствие она гораздо медленнее нативного массива символов.
адресом массива является адрес его первого элемента
обращение к элементам массива делается по смещению элемента относительно первого (чтобы обратиться к 3 элементу, берется адрес первого и к нему прибавляется число равное 2 * размер элемента).
то есть в принципе такая организация не позволяет хранить массивы с ассоциативными ключами.
как тогда хранятся ассоциативные массивы? а очень просто - любой массив в php, на самом деле, пара массивов. один из которых - массив ключей, а другой - массив значений.
таким образом, когда встает вопрос использовать функции array_keys и array_values или какой-нибудь цикл, думать даже начинать не надо.
потому что они вероятнее всего берутся прямо из памяти так, как есть. впрочем, если там бы использовался цикл, он был бы на несколько порядков быстрее цикла foreach, например.
6. тип ресурса
этот тип есть в пыхе, и в C. в C он называется по-другому. как? int. это всего-навсего число. особое между тем. это особый дескриптор (GUID - globally unique identifier - ну прям капец уникальный идентификатор в пределах всей ОС).
это число является ссылкой на соединение/поток (открытый файл) или что-то в этом духе. соответственно, когда соединение закрывается, и открывается по-новой, его GUID будет другим. а именно по этой причине кэширование, сохранение в сессии, в базе или где-то еще данных типа ресурс бессмысленно.
7. объект.
это область памяти, выделенная под его члены. соответственно, чем меньше динамических членов объявлено у класса и чем меньше каждый из них (строка меньше массива, булеан меньше числа), тем меньше памяти будет потреблять процессор php при создании нового объекта.
Передача по ссылке.
php позволяет передавать переменные по ссылке. это осуществляется тем, что в переменную пишется адрес в ОП другой переменной. таким образом когда мы вносим изменения в эту переменную, они на деле вносятся в переменную расположенную по этому адресу. Чтение данных производится тоже с этого адреса.
В классических языках программирования, передача по ссылке зачастую позволяет сэкономить память. Это далеко не всегда относится к php.
В php реализован механизм отложенного копирования. Рассмотрим пример кода:
$a = 10; // выделяется память под $a
$b = $a; // процессор php отмечает, что на область памяти с сохраненным числом 10, теперь ссылается две переменные
// то есть при таком присвоении, никакого выделения памяти еще не происходит, и в памяти до сих пор только одна переменная.
$b = 9; // при попытке присвоить значение одной из этих переменных,
// процессор смотрит есть ли еще ссылки на эту область памяти, и если есть, то
// под новое значение выделяется новая память
// таким образом здесь уже будет две отдельных переменных в памяти
несколько иначе дело обстоит с передачей по ссылке
$a = 10;
$b =& $a;
$b = 9;
здесь так как копирование было по ссылке, обе переменные будут указывать на новое значение. так как на старое больше не останется ссылок, оно будет стерто.
однако в следующей ситуации передача по ссылке заставит php выделять новую память
function func(&$a)
{
echo $a;
}
$a = 10;
$b = $a;
func($a);
Так как в функции $a может измениться, то php выделяет на нее память сразу же при передаче.
Спустя 5 дней, 10 часов, 50 минут, 30 секунд (11.12.2009 - 23:30) VolCh написал(а):
Про отложенное копирование не знал, подводные камни какие-нибудь есть?
Спустя 10 часов, 14 минут, 32 секунды (12.12.2009 - 09:44) glock18 написал(а):
Ну вот они собственно. Не нужно на ссылки много рассчитывать. Использовать их только если нужно поменять переданный параметр, но не для предположительного избавления от копирования данных.