Во многих (я бы даже сказал «во всех», но для этого мне нужно проверить все) реальных программах система типов в какой-то мере в голове у программиста, потому что ни встроенные типы, ни средства создания типов не могут точно смоделировать предметную область. Вот например:
char c = get();
if (c >= '0' && c <= '9') {
int digit = c - '0';
В большинстве языков вы никак не ограничите digit промежутком [0; 9] на уровне языка. И тип такой вам не дадут создать.
Понимаете, я не вижу даже где вы проводите черту. В тех же ассемблерах, например, из-за ограничений системы команд часто даже побитовое преобразование целого числа в число с плавающей точкой выполняется или отдельной командой или через память или ещё каким-то специальным образом. В данном отношении Си не менее «бестиповый», но тем не менее, вы его не относите к бестиповым.
И как это противоречит тому, что я сказал? Вы же будете использовать тип int? Будете. А ваша собственная структура «типов» будет только у программиста в голове.
Я не согласен с таким термином. Нельзя в термин вкладывать смысл что типов нет (как это вообще?) если на самом деле они есть (как вы сами сказали — битовые последовательности различной длины, можно давать и другие определения). И кроме того, если над ними ещё и производится проверки типов!
Смотрите сами: если вы оперируете какими-то значениями, то все такие допустимые значения принадлежат к какому-то множеству. И это множество и задаёт «тип». Поэтому я считаю сам термин «безтиповые» или «нетипизированные» некорректным.
> Никто не говорил, что значение N изменить нельзя или что сделать это сложно
>> Не существует легального варианта.
Вы же и говорили. Вы бы хоть не противоречили себе в соседних постах?
> Очень просто запутать себя, товарища, компилятор, пользователя, данные, если перезаписывать N новым значением прямо в цикле.
Компилятору всё равно N там переменная называется или не N. Если по правилам алиасинга этот указатель может указывать на N, то один раз на цикл загружать N в регистр компилятор не имеет права.
А если по алгоритму мне нужно эту переменную поменять, то я её нужно менять — при чём тут запутывание?
Я могу только сказать одно: удачи с отладкой. #define true false и то проще найти. И ещё, удачи с использованием современных инструментов определения data race.
Вы понимаете что v = a; не гарантирует что будет store в память? Инлайнинг и переупорядочивание записей сделают своё дело и этот стор может быть вынесен да практически куда угодно.
> Десятки лет люди писали абсолютно корректные в пределах широкого круга платформ многопоточные программы которые с точки зрения нового стандарта имеют UB.
Можно пример? (Два чтения — не race.)
> А вот чтение из массива целых без синхронизации из других потоков вполне применимо и безопасно для определенного класса алгоритмов.
Стандарт писали не глупые люди: два чтения — не data race по стандарту.
Это может быть нужно только если советы во-первых, правильные, во-вторых, с объяснением почему так, а в-третьих, спорные (полезность зависит от проекта и прежде чем применять стоит хорошо подумать) должны быть явно отмечены как таковые.
> и врядли когда-то будет.
Слышали ли вы про LLDB?
В большинстве языков вы никак не ограничите digit промежутком [0; 9] на уровне языка. И тип такой вам не дадут создать.
Ничего себе «если»! В Си вы даже malloc() без невного преобразования типа указателя вызвать не сможете.
> а в ассемблере — только когда они попали в регистры?
А в большинстве ассемблеров нет типа «указатель» (в некоторых есть, там где для указателей специальные регистры). Указатель — число нужного размера.
Я не согласен с таким термином. Нельзя в термин вкладывать смысл что типов нет (как это вообще?) если на самом деле они есть (как вы сами сказали — битовые последовательности различной длины, можно давать и другие определения). И кроме того, если над ними ещё и производится проверки типов!
Смотрите сами: если вы оперируете какими-то значениями, то все такие допустимые значения принадлежат к какому-то множеству. И это множество и задаёт «тип». Поэтому я считаю сам термин «безтиповые» или «нетипизированные» некорректным.
>> Не существует легального варианта.
Вы же и говорили. Вы бы хоть не противоречили себе в соседних постах?
> Очень просто запутать себя, товарища, компилятор, пользователя, данные, если перезаписывать N новым значением прямо в цикле.
Компилятору всё равно N там переменная называется или не N. Если по правилам алиасинга этот указатель может указывать на N, то один раз на цикл загружать N в регистр компилятор не имеет права.
А если по алгоритму мне нужно эту переменную поменять, то я её нужно менять — при чём тут запутывание?
habrahabr.ru/post/160995/#comment_5527441
Можно пример? (Два чтения — не race.)
> А вот чтение из массива целых без синхронизации из других потоков вполне применимо и безопасно для определенного класса алгоритмов.
Стандарт писали не глупые люди: два чтения — не data race по стандарту.
Очевидно, что можно вызвать f(&N, &x); где x это какая-то другая переменная.
> friend-аттрибут
friend — не атрибут.
> Старайтесь писать вместо int* a → int a[].
Вредный совет. int a[] автоматически заменяется (type adjustment) на int *a во многих местах, например, в параметрах функции.
> Если нужно указать точный размер массива, передаваемого в функцию, сделайте аргумент ссылочного типа:
> void Foo(int (&array)[42]);
Я бы не хотел это поддерживать. std::array же.
> tips.wincode.org/#24
И зачем этот хак? А как же mutable?
И так далее, к каждому второму совету у меня есть уточнения или претензии?
Ссылки на разделы стандарта следует писать в удобочитаемом виде, а не в виде номера раздела (например, [lex.icon]).
Что-что?! o_O
Совсем нет, главное просто сериализовать внутреннее представление (и не генерировать никакой машинный код) в объектные файлы.
А я говорил о том, что чем больше IPA видит, тем лучше (например, тем лучше инлайнинг).