Ленин

Aug 19, 2015 11:23

(В заголовке - старинный каламбур про Ленина в ссылке.)

Короче говоря, дошёл до реализации сущностей, именуемых разными нехорошими словами - "указатели" самое безобидное из них. На сишные указатели лисповые похожи, но не совсем.

Вот, например, как мы делаем в Си, если хотим присвоить какой-то переменной какое-то значение:
int a = 2;Как это ( Read more... )

uncommon lisp

Leave a comment

psilogic August 19 2015, 18:55:13 UTC
в сях переменная обозначает не адрес, а имя некой области памяти и абстрактное "значение" переменной
чтобы получить адрес, надо еще применить операцию &
кроме массивов и функций где это необязательно

Reply

kincajou August 19 2015, 19:00:31 UTC
сама переменная - это уже адрес, для компилятора. А если мы хотим получить ЗНАЧЕНИЕ адреса, тогда нужна операция &.

Reply

psilogic August 19 2015, 19:08:17 UTC
для компилятора сама переменная это много чего - как минимум адрес, размер, битовое содержимое, тип, способ аллокации

(в том смысле, что компилятору крайне желательно всё это знать и учитывать)

Reply

kincajou August 19 2015, 19:11:27 UTC
ёпрст. Имя указывает на адрес "чего-то", а что это за "что-то" описано в обхявлении переменной. Си тупой, для него переменная - это в самом деле просто адрес без ничего. Поэтому и невозможно создавать переменные без типов - они всегда должны быть описаны хоть как-то

Reply

psilogic August 19 2015, 19:14:47 UTC
нет погоди. вот размер где-то прикапыывается? имеется в виду не на рантайм, а во время компиляции. прикапыывается. и ассоцируется с именем. именно поэтому sizeof(x) - константа - потому, что она на уже этапе компиляции известна. соответственно компилятор должен этот размер где-то хранить - опять же в процессе компиляции

вот я об чем

а ты наверное об RTTI

Reply

kincajou August 19 2015, 19:24:47 UTC
на этапе компиляции компилятор знает много чего...

Reply

psilogic August 19 2015, 19:31:09 UTC
Экономят же... ты вон каждый битик экономишь, так и тут.

Чтобы хранить runtime информацию надо как минимум ссылочку на инфу о переменной - то есть или просто адрес или индекс для поиска в неком контейнере.

Поэтому по-умолчанию память не расходуют. Но только по-умолчанию. Всегда можно включить - для того и существуют виртуальные методы класса. А также родное мелкомягкое RTTI.

Reply

kincajou August 21 2015, 09:31:57 UTC
насчёт экономии... подумал, что многие символы, которые называются простыми и понятными именами типа i, j, k и т.п., слишком роскошно было бы хранить в динамически выделенных строках. Ведь когда длина имени меньше, чем размер указателя на него, есть смысл как-то извратиться и вместо указателя вписать саму строку, как я сделал с числами.

Красиво и изящно пока не удалось.

Reply

kincajou August 19 2015, 19:29:28 UTC
sizeof(x) это вообще что-то вроде макроподстановки, насколько я знаю. Не совсем макрос, не совсем функция - какой-то грязный хак. Как оно работает и почему так нельзя было сделать какой-нибудь typeof(x), чтобы он возвращал ну хотя бы указатель на const char*, где была бы строка с названием типа (вот совсем тупо так) - ...

Reply

psilogic August 19 2015, 19:33:38 UTC
typeof вполне могли бы сделать, ты прав

вот даже и не знаю, почему не сделали - хотя б для тех переменных, для которых это константа

Reply

kincajou August 19 2015, 19:14:58 UTC
если бы это было иначе, в Си ВНУТРИ программы можно было бы узнать, что за переменную мы получили - например, взять указатель на "что-то" и узнать тип этого "чего-то". Но увы

Reply

kincajou August 20 2015, 07:21:30 UTC
вощем, с прискорбием контстирую - легко портировать на 16-битные машинки (и уж тем более на 8-битные) не выйдет без очередного перелопачивания кода (после перелопачивания, которое я затеял сейчас!), но на 32-битных и более широких - работать такой подход будет.

Ну или на каких-то кастомных, где мы можем выделить два бита под тэг к каждому указателю. Больше вроде не надо. Получается стройно и аккуратно, в теории: четыре типа указателей -- на "значение", на "список", на "символ" и просто "ссылка".

Значение хранит значение (спасибо, К.О.), список хранит список "чего-нибудь", символ хранит пару [ИМЯ."что-то"], "ссылка" косвенно указывает на "что-то".

Соотв., те сишные функции, которые должны работать с "чем-то", сначала извлекают тэг, и в соответствии с ним уже делают задуманное.

Reply

kincajou August 21 2015, 09:33:13 UTC
а зато! а зато!!! вот теперь что работает:

(SETF Z (CONS "A" "B"))
(SETF Z (CONS ( CDR Z ) (CAR Z) ) )

первая команда создаёт символ Z, в котором лежит пара ( "A" . "B" ), а второй вызов элегантно меняет местами элементы пары и записывает обратно. И оно работает!

Reply

psilogic August 21 2015, 09:59:52 UTC
а соответствующий сишный код займет меньше места, чем эти две строчки? :)

Reply

kincajou August 21 2015, 11:08:13 UTC
Нет, гораздо больше. Потому что работающий под этим слой сишного кода написан в обобщённом виде. В любое место списка можно воткнуть что угодно: другой список (или точечную пару), атомарное значение, символ или ссылку. При этом память корректно выделяется и высвобождается, нулевые указатели не разыменовываются и т.п., и т.д.

Reply


Leave a comment

Up