Для понимания нужно вспомнить историю Си. Пара аспирантов и пара студентов делала структурный ассемблер для PDP-7. Машина была словной (16 битные слова), а язык безтиповым и назывался Би.
От PDP-7 в языке Си остались такие конструкции как эквивалентность arr[i] и *(arr+i). На безтиповом языке для словной машине это было просто сложение.
Когда они решили перейти на PDP-11, безтиповым языком было уже не обойтись. PDP-11 была словной машиной с адресацией до байта. То есть по четном адресу можно было прочитать и слово и байт, а по нечетному — только байт. Поэтому им пришлось вводить типы. Ну и сменить название языка на Си.
И тогда, для ускорения переделок, была придумана гениальная идея. Вместо описания типа — описывать, какими преобразованиями переменная приводится к базовому типу. int **pp означает, что если дважды разыменовать pp, то получиться int. Этих хаком они упростили себе переделку компилятора,
От PDP-11 в Си осталась конструкция *dst++ = *src++, которая транслировалась в одну команду mov (R5)++, (R3)++
Если бы вы начали изучение Си с The C Programming Language, то там довольно явно рассказывается об этом…
Ну а первые впечатления от Си (1984 год): вау, какой красивый ассемблер! Теперь можно писать код на ЯВУ и понимать, какие команды будут исполняться! Особенность компиляции (из.с в .s, а уж потом в .obj) этому только помогали.
Но да, к 1990ому году пришли иные машины и иные компиляторы. И Си перестал восприниматься ассемблером конкретной машины. А хак с заменой описания переменных на описание преобразования в базовые типы — остался.