Как строятся типы в Си
2025-05-15 23:54Простой ли язык Си? Я покажу вам как в нём строятся типы, и вы сами решите. (Подсказка: непростой.)
Я задумал некий сложный тип. Будем строить его по шагам. Что он по большому счёту представляет? Указатель. Ставим звёздочку.
Что находится в каждом элементе массива? Указатель. Добавляем звёздочку слева.
А чтобы совсем весело стало, добавим внутрь слово static.
Я задумал некий сложный тип. Будем строить его по шагам. Что он по большому счёту представляет? Указатель. Ставим звёздочку.
На что указывает наш указатель? На массив. Ставим круглые скобки вокруг звёздочки и дописываем квадратные скобки справа.*
Сколько элементов в массиве? Пять. Ставим пятёрку внутри квадратных скобок.(*)[]
(*)[5]
Что находится в каждом элементе массива? Указатель. Добавляем звёздочку слева.
На что указывает этот указатель? На функцию. Какие аргументы принимает функция? Один аргумент типа char. Заворачиваем нашу конструкцию в круглые скобки и справа в круглых скобках добавляем аргументы.*(*)[5]
Что возвращает функция? Тип int. Дописываем слева.(*(*)[5])(char)
Таким образом, мы имеем указатель на массив из пяти указателей на функции, принимающие char и возвращающие int. Не пытайтесь повторить на трезвую голову. 😀int (*(*)[5])(char)
А чтобы совсем весело стало, добавим внутрь слово static.
Получили указатель на массив из не менее чем пяти указателей на функции, принимающие char и возвращающие int.int (*(*)[static 5])(char)

no subject
Date: 2025-05-16 07:13 (UTC)А ещё добавить звёздочку, если функция возвращает указатель на int.
no subject
Date: 2025-05-16 07:16 (UTC)no subject
Date: 2025-05-16 07:19 (UTC)no subject
Date: 2025-05-16 07:44 (UTC)no subject
Date: 2025-05-16 07:22 (UTC)no subject
Date: 2025-05-16 08:07 (UTC)Указатели на функции уже нетривиальны.
no subject
Date: 2025-05-16 15:47 (UTC)Залежить від того, на що це кандидат. Можна було писати дофіга всього обчислювального і навіть десь в чомусь нетривіального, але ніколи далі простих скалярів і тензорів не далі 3-4 порядку не рухатися.
Для наукових чиінжерених обчислень Сі зручний в першу чергу динамічною алокацією-деалокацією памʼяті і парочкою додаткових фіч, завʼязаних на поінтери. (Дисклеймер: злі язики кажуть, що фортран 90 то всьо теж має. Не знаю, не пробував)
no subject
Date: 2025-05-16 14:34 (UTC)no subject
Date: 2025-05-16 08:38 (UTC)no subject
Date: 2025-05-16 08:24 (UTC)"Указатель на массивъ изъ указателей на функцiи, принимающiя char и возвращающiя int."
"Указатели" мы вообще не пишемъ, потому что всѣ типы являются указателями по умолчанiю. Компиляторъ самъ найдетъ, когда можно написать просто int вмѣсто указателя на int.
(Указатель на int и просто int - это одно и то же, потому что вѣдь всѣ значенiя являются константами и ихъ нельзя модифицировать на мѣстѣ.)
Итакъ, намъ нуженъ "массивъ функцiй изъ char въ int". Просто записываемъ эту фразу:
И все. Читается и пишется легко. Благодаря такому синтаксису, можно и гораздо болѣе сложные типы опредѣлять и использовать безъ существенныхъ проблемъ. Никакихъ звѣздочекъ и скобокъ безъ конца, никакихъ этихъ "*(*(*)[*(*)])", которые всѣхъ совершенно запутываютъ и дѣлаютъ кодъ нечитаемымъ.
Если мы все-таки хотимъ явно выписать указатели (скажемъ, если мы пишемъ библiотеку для работы съ устарѣвшими языками, такими, какъ B или C), то мы дѣлаемъ конструкторъ Pointer и пишемъ:
Немного сложнѣе, но все равно читаемо.
Теперь, если мы хотимъ указать минимальную длину массива, это отдѣльная задача. Обычно это рѣшается съ помощью рафинированныхъ типовъ ("refinement types"). На Скалѣ это выглядитъ такъ (библiотека refined https://github.com/fthomas/refined )
На Хаскелѣ тоже есть полностью аналогичная библiотека refinement types, но я недостаточно съ этимъ пока знакомъ, чтобы такъ навскидку написать примѣръ использованiя. (Спрашивать объ этомъ ИИ - зашкваръ.)
И можно задавать любыя дополнительныя условiя на длину массива. Скажемъ, что длина массива отъ 5 до 10 элементовъ, или что массивъ всегда нечетной длины - нѣтъ проблемъ.
Идея, что типы должны быть написаны на понятномъ человѣку языкѣ, такъ что типы любой сложности будетъ можно достаточно легко читать и писать, была реализована уже въ 1983 году въ языкѣ Standard ML, изъ основныхъ идей котораго и произошли сегодняшнiе языки OCaml, Haskell, Scala.
https://smlfamily.github.io/history/SML-proposal-11-83.pdf
А первыя идеи, приведшiя къ этому языку, были еще въ 1975 году открыты.
https://dl.acm.org/doi/10.1145/3386336
Языкъ СAml, изъ котораго вышелъ сегодняшнiй OCaml (продолжающiй ту же традицiю строго типизированныхъ языковъ съ полнымъ выводомъ общихъ типовъ и доказанной непротиворѣчивостью семантики типовъ):
https://web.archive.org/web/20220120003835/https://caml.inria.fr/about/history.en.html
no subject
Date: 2025-05-16 15:45 (UTC)В суслике (golang) операции с типом Type "объясняют" то же самое, только сверху-вниз.
А конструкция типа static 5 это что то новое в сишной грамматике?
no subject
Date: 2025-05-16 16:13 (UTC)https://en.cppreference.com/w/c/language/array
no subject
Date: 2025-05-16 17:07 (UTC)Отстал от прогресса.
Попытался сходу придумать, зачем бы это мне пригодилось. Сходу не вышло.
Но, как я понимаю, реализация в компиляторе несложна. Просто ещё один параметр (или флажок) в аст-дереве в объекте array.
no subject
Date: 2025-05-16 19:00 (UTC)Зачем - не понимаю.
no subject
Date: 2025-05-16 19:34 (UTC)Incorporate into C what was invented for C++.