В этой статье автор пытается рассказать о том, чем являются имена массивов в Си. Он показывает, что a и &a имеют одно и то же числовое значение, то разные типы. Имя a является указателем на первый элемент массива и имеет тип int *, а &a - то же самое, что &a[0], и является указателем на массив из трех чисел.
Пример в конце статьи:
preserve do
:escaped
(gdb) print a + 1
$10 = (int *) 0x7fff5fbff570
(gdb) print &a + 1
$11 = (int (*)[3]) 0x7fff5fbff578
И цитата автора: Note that adding 1 to a adds four to a’s address, whereas adding 1 to &a adds twelve!
Почему здесь написано, что к &a прибавляется 12, когда по логу видно, что прибавляется 8?
Почему прибавление единицы к &a инкрементирует значение гораздо больше, чем прибавление единицы к a? Что это за игра с типами такая?
Ответ
По поводу первого вопроса
Почему здесь написано, что к &a прибавляется 12, когда по логу видно, что прибавляется 8?
Стоит обратить внимание, что в логе отображены результаты сложения, и между ними разница действительно 8 и это вводит в заблуждение. Но, чтобы узнать сколько прибавилось, нужно смотреть на начальный адрес
= preserve do
:escaped
(gdb) x/4xb a
0x7fff5fbff56c: 0x01 0x00 0x00 0x00
(gdb) x/4xb &a
0x7fff5fbff56c: 0x01 0x00 0x00 0x00
И если смотреть разницу относительно него, то можно увидеть, что в первом случае она равно 4, а во втором - 12 как и написано в статье.
Что касается второго вопроса
Почему прибавление единицы к &a инкрементирует значение гораздо больше, чем прибавление единицы к a? Что это за игра с типами такая?
то возможно поможет перевод аналогичного вопроса на английском
Имя массива обычно вычисляется как адрес первого элемента, так что array и &array имеют одинаковое значение (но разные типы, array+1 и &array+1 не будут равны, если длина массива больше одного элемента).
Есть два исключения из этого правила: когда имя массива является операндом sizeof или унарного & (address-of) имя указывает на сам массив, поэтому sizeof возвращает размер всего массива, а не размер указателя.
Для массива определенного как T array[size], array будет иметь тип T *. При инкрементировании его вы получите следующий элемент в массиве.
&array возвращает тот же адрес, но при этом тип указателя будет уже T(*)[size] - т.е. это указатель на весь массив, а не отдельный элемента. И когда вы увеличиваете этот указатель он добавляет размер всего массива, а не размер отдельного элемента.
Комментариев нет:
Отправить комментарий