Есть несколько заблуждений насчет e-mail-маркетинга, которые приобрели широкое распространение. e-mail-маркетинг — это СПАМ. Основное отличие e-mail-маркетинга от спам-рассылки состоит в том, что первый — это коммуникация с подписчиками собственной базы e-mail адресов по их предварительному согласию, а вторая — это массовая рассылка материалов рекламного характера по базам e-mail адресов из открытых источников, без согласия получателей, что в свою очередь нарушает закон в любой стране мира.
Как я понял из статьи, никакого предварительного согласия ни с какими подписчиками у вас не было, следовательно вы занимались т.н. спамом.
Довольно долго я никак не мог понять, как с подобным уровнем знаний все эти молодые люди сумели сдать БАК, задачи в котором, как правило, составлены на вполне приличном уровне и решить которые (как мне казалось) можно, лишь обладая вполне приличными знаниями. Теперь я знаю ответ на этот вопрос. Дело в том, что практически все задачи, предлагаемые на БАКе, можно решить с помощью хорошего калькулятора - они сейчас очень умные, эти современные калькуляторы: и любое алгебраическое преобразование сделают, и производную функции найдут, и график ее нарисуют. При этом пользоваться калькулятором при сдаче БАКа официально разрешено. А уж что-что, а быстро и в правильном порядке нажимать на кнопочки современные молодые люди учатся очень лихо. Одна беда - нет-нет да и ошибешься, в спешке не ту кнопочку нажмешь, и тогда получается конфуз. Впрочем, "конфуз" - это с моей, старомодной, точки зрения, а по их, современному, мнению - просто ошибка, ну что поделаешь, бывает. К примеру, один мой студент что-то там не так нажал, и у него получился радиус планеты Земля равным 10 миллиметрам. А, к несчастью, в школе его не научили (или он просто не запомнил), какого размера наша планета, поэтому полученные им 10 миллиметров его совершенно не смутили. И лишь когда я сказал, что его ответ неправильный, он стал искать ошибку. Точнее, он просто начал снова нажимать на кнопочки, но только теперь делал это более тщательно и в результате со второй попытки получил правильный ответ. Это был старательный студент, но ему было абсолютно "до лампочки", какой там радиус у Земли: 10 миллиметров или 6400 километров, - сколько скажут, столько и будет. Только не подумайте, что проблему можно решить, запретив калькуляторы: в этом случае БАК просто никто не сдаст, дети после школы вынуждены будут вместо учебы в университетах искать работу, и одновременно без работы останется целая армия университетских профессоров - в общем, получится страшный социальный взрыв. Так что калькуляторы трогать не стоит, тем более, что в большинстве случаев
А с получившимся после дегалогенирования дифенилом что потом можно делать? Какой он будет чистоты? ПХБ находится при стандартном давлении и температуре в жидком состоянии, дифенил твердый. Дифенил наверняка будет в этом ПХБ растворяться в процессе дегалогенирования, а потом начнет выпадать в осадок. Так вот, не будет ли дифенил после коллоидной мельницы содержать в себе примеси ПХБ в опасных концентрациях?
А можно ли деактивировать хлордифенил карбидом кальция? Как вообще хлорорганика реагирует с карбидами щелочных и щелочноземельных металлов? Например, если хлорбензол с карбидом кальция: C6H5Cl + CaC2 нагревать, какие будут продукты? Можно ли так синтезировать C6H5-C≡C-C6H5?
Там, к примеру, рукой создателя языка написано следующее: ...
Это очень похоже на текст стандарта?
Может и похоже чем-то, но нет, текстом стандарта это не является. Например вот фрагмент
6.1 Characters and integers
A char object may be used anywhere an int may be. In all cases the char is converted to an int by propagating its sign through the upper 8 bits of the resultant integer. This is consistent with the two’s complement representation used for both characters and integers. (However, the sign-propagation feature disappears in other implementations.)
The handling of overflow and divide check in expression evaluation is machine-dependent. All existing implementations of C ignore integer overflows; treatment of division by 0, and all floating-point exceptions, varies between machines, and is usually adjustable by a library function.
Machine-dependend уже предполагает, что есть не только лишь PDP-11. В K&R даже в первой редакции написано, что число бит в байте может быть разным, и тут уже явно упомянут не только PDP-11:
Во-первых, как я уже сказал, Паскаль - это не Си, и такое поведение в нем всегда было определено как Error. Во-вторых, прочитайте внимательно тот текст стандарта Паскаля, который я процитировал. Описанное там поведение сильно отличается от того, что говорит о знаковом переполнении стандарт Си. Если реализация Паскаля соответствует пунктам 2 или 3, то тогда ваша программа в худшем случае аварийно завершит исполнение, в то время как аналогичная программа на Си может, согласно стандарту, сделать что-угодно.
И что? Программы-то могут перестать работать, если в одной реализации программа работает нормально, а в другой получается Error? Вы жалуетесь, что программы на Си перестали из-за плохого стандарта работать, сломались работавшие когда-то сишные программы. Так вот, паскаль так тоже умеет. В одном компиляторе паскаля Integer один, и всё работает, в другом компиляторе паскаля Integer другой, и все сломалось. Паскаль должен умереть?
Что такое достаточно эффективный код для фоннеймановских архитектур? И при чем тут упомянутые вами в предыдущем сообщении абстракции?
Что касается Си и Паскаля, то они достаточно легко ложится на фон-неймановские архитектуры, можно код функций перевести в код на ассемблере, при вызове функций, адрес возврата (место, откуда функция была вызвана) записывается в стек. Функции в процессе работы выделяют себе место в стеке под локальные переменные, есть передача аргументов в эти функции, для этого есть определенные соглашения вызовов, в адресном пространстве процесса еще есть область для глобальных и статических переменных. И эти языки явно делали с оглядкой на то, чтобы их было удобно компилировать. А некоторые языки на это так просто не натягиваются, например Prolog. И язык Prolog работает на другом уровне абстракций. Так понятней?
Когда же я говорю, что Си - это язык низкого уровня, я подразумеваю, что его описание напрямую зависит от реализации компилятора и особенностей компьютера PDP-11.
Его еще в первой редакции "The C programming language" в 1978 году начали от PDP-11 отвязывать, разрешив разное количество бит под байт, и упомянув архитектуры, отличные от PDP-11. Уже тогда Си должен был умереть?
То, что реализация компилятора не позволила реализовать на нем memcpy не говорит о том, что gcc - это неправильный компилятор языка Си. Это поведение абсолютно валидно с точки зрения стандарта - никто вам такой функционал предоставлять не обязан.
Еще раз. Критерием "баг это или не баг" я считаю статус в багзилле GCC. В багзилле GCC это подтвердили как баг - значит это баг GCC. Баги это по-вашему только те случаи, когда некое поведение компилятора не соответствует стандарту?
Что вы имеете в виду под частично совместимым? C89 - это не частично совместимый с Си язык, а его единственно верный, как уверяет комитет, вариант
То и имею в виду, что допустим вместо C89 выпустили бы "Extended-C", а Си оставили б в состоянии на момет выхода K&R. Это было бы существено лучше, это бы что-то радикально изменило?
Не нравится официальный стандарт - изобретите свой стандарт и сделайте там так, как вам нравится. Есть достаточно много ответвлений от языка Си.
Тут же случилось так, что все написанные к 89-ому году работающие программы на Си неожиданно в одну секунду оказались, согласно стандарту, неработающими.
Совсем-совсем все, т.е. 100% программ вдруг стали неработающими? Неработающими с точки зрения стандарта C89? А с точки зрения K&R они точно все были работающими? В K&R например написано, что бит в байте может быть 8, а может быть больше чем 8 - если какая-то программа полагается на то, что байт 8-битный, она может не заработать на архитектуре с 9-битным байтом. Или наоборот, если предполагается, что байт 9-битный, программа с 8-битным байтом может не работать корректно.
Паскаль всегда был и остается языком высокого уровня, поэтому размер типа Integer там не указан намеренно.
А какое это имеет отношение к "уровневости"? В Си кстати тоже размер int не указан, получается что он в вашей классификации язык высокого уровня? Вот в Java размер типа int как раз указан, выходит что Java это язык низкого уровня? https://docs.oracle.com/javase/specs/jls/se17/html/jls-4.html#jls-4.2 : The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units (§3.1).
Причем сам Error стандарт Паскаля определяет гораздо мягче, чем Undefined Behavior у Си.
Это не отменяет того факта, что программы на языке Паскаль могут перестать работать из-за того, что тип Integer вдруг стал другим, и не вмещает в себя нужный диапазон. Так что же получается, "Паскаль должен умереть"?
В любом случае Паскаль, в отличие от Си, никогда за свою историю не определялся как язык низкого уровня.
Где в стандарте языка Си написано, что Си это язык низкого уровня?
Где в стандартах Си или Паскаля указано, что они компилируется в машинные коды?
Нигде. Вполне можно интерпретировать Си, впрочем как и Паскаль. Впрочем, как и ассемблер x86. Я о том, что Си и Паскаль можно компилировать в достаточно эффективный машинный код для фон-неймановских архитектур.
Для языка высокого уровня безразлично, каким образом будут транслироваться написанные на нем программы.
А для языка низкого уровня не это безразлично? Писать интерпретаторы ассемблера незаконно? Что значит "для языка безразлично", у него какое-то свое мнение есть? Что вообще такое язык высокого и язык низкого уровня? Я язык Си не считаю языком низкого уровня, язык низкого уровня для меня это ассемблер, машинный код.
Как багом может являться документированное поведение компилятора?
Багом это является по причине того, что в багзилле GCC признали, что это баг.
Проблема - это программа, которая не работает. А не работает она в том числе потому, что комитет стандартизаторов посчитал возможном полностью изменить семантику языка, который к тому моменту существовал уже 20 лет.
Был старый код, а стал неработающий код. Если у комитета была задача сломать как можно больше кода (и старого, и нового), то они ее достигли с большим успехом.
Т.е. надо было ничего в Си не менять, а создать новый язык, и было бы всем счастье? Ну допустим не меняли бы они ничего, выпустили бы вместо C89 новый частично совместимый с Си язык, назвали бы его как "Extended-C" например, напихали бы туда этих оптимизаций через неопределеное поведение при стрикт-алиазинге и прочее, на что вы тут жалуетесь, старые программы портировали бы на этот "Extended-C" а сам исконно-посконный Си забросили бы, как забросили языки B и BCPL, и что бы от этого принципиально поменялось?
Си, созданный Ритчи, был языком для конкретной машины. Как только он вылез за рамки PDP-11, начались проблемы.
А в каких случаях проблем бы не было? Вот например в паскале у Integer какой размер в байтах? https://archive.org/download/iso-iec-7185-1990-Pascal/iso-iec-7185-1990-Pascal.pdf - попробуйте там что-нибудь найти про это. На 55 странице этого PDF файла есть упоминание про maxint, который (сюрприз!) implementation-defined. Если посмотреть сюда https://wiki.freepascal.org/Integer - тут сказано Typical sizes of integer generally are 16 bit (2 byte), 32 bit (4 byte) or 64 bit (8 byte) - отлично, т.е. если кто-то в своей программе на паскале предполагает, что Integer 32-битный, на паскале с 16-битным Integer его код корректно не заработает. А если бит не 8-битный? Какие компилируемые в машинный код языки программирования, сопоставимые по уровню абстракции с тем же Си или паскалем, могут работать на (т.е. компилироваться под) архитектурах с не 8-битным байтом, чтобы код при этом не нужно было переделывать? Может надо делать отдельный язык для архитектур с 8-битным байтом, отдельный для 9-битного байта, отдельный для 16-битного байта, отдельный язык для two's complement, отдельный для one's complement знаковых чисел, и так под каждую архитектуру делать язык с особым уникальным именем?
The Prime 50 series used segment 07777, offset 0 for the null pointer, at least for PL/I. Later models used segment 0, offset 0 for null pointers in C, necessitating new instructions such as TCNP (Test C Null Pointer), evidently as a sop to [footnote] all the extant poorly-written C code which made incorrect assumptions.
Это не баг, -nostdlib работает так, как написано в документации gcc:
Ну ок, значит не -nostdlib а какой-то другой флаг не сработал. Я просто привел цитату из багзиллы GCC.
Багом GCC является то, что использование некоторых флагов не позволяет эту оптимизацию отключить. То, что по стандарту (т.е. не используя специальных опций компилятора) нельзя написать свою реализацию memcpy, не является серьезной проблемой языка Си, т.к. во-первых такие функции не надо каждый день писать и во-вторых, это решается специальными флагами компилятора. Серьезных проблем в Си хватает, но это не одна из них
Ну так и сделали бы новый, прекрасный, переносимый, легко оптимизируемый язык
Под который нужно было бы переписывать весь старый код? А кто сказал, что такой язык никто не сделал? Вот D например есть. Или Rust.
Почему не сделали совместимый с Си язык, назвав его по-другому? Тоже сделали, называется он "C++", есть еще "Obj-C". Хотя насчет прекрасности я б тут поспорил.
Зачем было брать прибитый ржавыми гвоздями к архитектуре PDP-11 Си и вводить в заблуждение кучу людей?
Потому что под Си написано много кода, и его хотелось бы не переписывать, а дорабатывать. Введение в заблуждение в чем заключается? Си времен K&R был хорошим, а потом стал плохим? Вот например вы ругаете правила сравнения указателей:
Вот небольшой фрагмент кода, демонстрирующий некорректное с точки зрения стандарта сравнение:
int *p = malloc(64 * sizeof(int));
int *q = malloc(64 * sizeof(int));
if(p < q) /* Undefined behaviour! */
do_something();
>K&R 1, page 98: >"But all bets are off if you do arithmetic or comparisons with pointers >pointing to different arrays. If you're lucky, you'll get obvious >nonsense on all machines. If you're unlucky, your code will work on one >machine but collapse mysteriously on another."
Т.е. реализация memcpy должна быть настолько сложной, чтобы компилятор не смог оптимизировать ее исходный код - прекрасно!
Скорее так: если нужно реализовывать memcpy и прочие функции из стандартной библиотеки Си, нужно использовать специальные флаги компилятора или прагмы, не дающие компилятору соптимизировать это в рекурсию. Программисты редко когда свой memcpy реализовывают, так что это не то чтобы большая проблема.
Почему вы считаете, что это баг компилятора? Компилятор ведет себя в соответствии со стандартом (4.1.2 Standard headers):
Now, if this replacement still happens when you compile with -nostdlib, that would be a bug since it becomes legal code in that case.
Т.е. флаг -nostdlib по-идее должен это разрешать, а он не разрешает. Там советуют использовать опцию -fno-tree-loop-distribute-patterns
Можно использовать для таких функций attribute ((optimize ("-fno-tree-loop-distribute-patterns")))и тогда должно нормально компилироваться без рекурсий.
И это заблуждение поддерживалось в том числе комитетом стандартизаторов - для чего было вводить столько UB, перекладывая ответственность на создателей компиляторов, и делать вид, что с Си ничего не произошло?
Для переносимости и для более агрессивной оптимизации.
Мы упомянули о том, что пароль (или его часть) может остаться в регистре. На самом деле ответ прост - в рамках самого языка Си эта проблема неразрешима. В тексте стандарта даже, очевидно, слово "stack" не упоминается - об очищении чего тогда вообще может идти речь?
А где она разрешима? Кроме ассемблера, я не слышал о других языках, которые бы давали такой уровень контроля. Как такой язык должен выглядеть, если это будет не ассемблер?
Но вообще можно придумать некую специальную прагму, которая заставит всё тот же компилятор Си генерировать код зануления стекфрейма и регистров по выходу из функции.
Попробуем предположить, какой результат у нас получится.
Если размер байта больше 8 бит (такое вполне бывает и разрешено стандартом), ничего страшного не произойдет. Если хочется получить UB, лучше использовать макрос CHAR_BIT
int x = 1;
x = x << sizeof(int) * CHAR_BIT;
Кстати, тут можно и unsigned int взять. Если unsigned int 32-битный, сдвиг единицы на 32 тоже будет UB.
Для своей операционной системы разработчик решил использовать собственную реализацию функции memset. Но он не учёл, что в процессе трансляции компилятор gcc обнаружит в этом коде весьма заманчивую возможность для оптимизации.
Есть лишь одна проблема - после вызова check_password в стеке останется строка с настоящим паролем пользователя. Если в вашей программе есть хотя бы одна уязвимость, позволяющая читать данные из памяти, то существует реальная вероятность украсть пароль из стека.
А еще существует вероятность, что какие-то куски пароля останутся в каких-нибудь регистрах, как это проконтролировать? Может тогда на ассемблере писать, ну что уж точно ничего случайно не просочилось? И кстати пароли в открыдом виде не хранят, а хранят их хэши.
Там есть такая замечательная строчка, как a = b = c = d = e = f = g = h = T1 = 0; , где все эти a b c d ... являются локальными переменными в этой функции. Что вообще автор хотел этим сказать? Видимо он хотел избежать утечки каких-то данных через стек, и даже возможно через регистры. Компилятор это зануление локалок конечно имеет право выкинуть, но ДОПУСТИМ он не выкинет их, и действительно занулит соответствующие регистры и стек. Только в стеке и в регистрах могут быть записаны какие-нибудь промежуточные результаты вычислений, а их как вообще занулить? Писать специализированный компилятор, который все использованные функцией адреса в стеке и все использованные регистры (кроме возвращаемого значения) забивает нулями?
Мне из цитаты неясно, что такое "суть". Нужно определение слова "суть" в данном контексте.
Доказать не-сущестсование нельзя. Это научный метод. Чайник Рассела погуглите
Доказать не-существование чайника Рассела в определенном конкретном месте и в определенное время очень даже можно. Например, какой-нибудь телескоп доказывает через свои камеры, что в некоторой конечной области пространства сейчас никаких чайников нет. И космонавты в открытом космосе тоже доказывают, что мимо них чайники сейчас не пролетают. А доказать "вообще нигде во Вселенной нет ни одного чайника" будет уже затруднительно.
Кстати, а как бы вы доказывали, что между Землёй и Марсом вокруг Солнца вращается по крайней мере один чайник Рассела? Допустим, кто-то шутки ради действительно отправил на орбиту такой чайник, и его удалось увидеть на снимках с телескопа, но где гарантии, что снимки с телескопа не были специально подделаны какими-нибудь шутниками? А где гарантии, что всё это не ваш сон? Что будет считаться доказательством?
Если есть только ничто - значит у нас есть 0 единиц «чего-то»? По идее да, но ведь есть само - ничто. Значит 1 единича чего-то? Значит уже ничто - это не «никакого чего-то», а значит логический тупик.
По каким причинам мы само наличие "ничто" принимаем за "1 единицу чего-то"? Оно же на то и "ничто", что его нет, так что никакой "1 единицы ничего" нет, и дальнейшие рассуждения смысла не имеют.
Иррациональное мышление живет в идеалистическом мире, который живет в хаосе, не подчиняясь никаким законам.
Наличие каких-либо законов физики нельзя строго доказать. Можно поставить счетное и конечное множество экспериментов, и на основе полученных данных можно построить некую физическую теорию, по которой можно было бы с какой-то точностью предсказывать "что будет, если ...".
Сначала было ничто. То есть не было ничего. Иначе - ничто это отсутствие всего.
Где (в чем) оно было? Или оно было "само в себе"? Что вообще означает "быть"? Откуда мы можем знать, что это "ничто" реально когда-то было? А что если "быть" вообще неприменимо к "ничто"?
В ничто не было ни пространства, ни материи, ни отношений, ни движения, ни чего-либо иного кроме самого ничто.
ОК, допустим. И зачем понадобилось предполагать, что когда-то в самом начале было некое "ничто"?
Когда было одно лишь ничто, и ничего другого - существовало ли оно? Существовать - значит иметь в себе суть, то, что в полной мере показывает его отличие от чего-либо другого.
Что значит "иметь в себе суть"? Что такое "суть"?
Однако если у ничто была суть, то есть отличие - значит ничто было не одно, ведь невозможно описать отличие ничто от ничто - ведь это одно и то же.
Пусть будет одно единственное "ничто", и никаких других "ничто" не будет. Почему должно быть проблемой то, что кто-то в рамках некоторой формальной системы что-то не может описать?
Логика подводит нас к одному единственному правильному суждению - существование ничто приводит и к существованию нечто, как к некоему противовесу, позволяющему описать отличие ничто от нечто.
А если логика неправильная, и на самом деле существование "ничто" ни к какому существованию "нечто" не приводит? Что такое "нечто"? И кстати, какая логика, классическая или интуиционистская(нет закона исключённого третьего)? Или может какая-то своя? Есть еще многозначные логики, модальные логики и проч.
Откуда взялась уверенность, что используемая вами логика адекватно описывает предметную область, и дает верные выводы о сущности вещей, что что-то там существует если вот то существует? См. https://youtu.be/u1AyoXrXYe4?t=1263 (почему можно поставить под сомнение тезис, что 2*2=4)
Ничто и нечто - явления одного порядка, описывающие друг друга, и существовать друг без друга не могут, ибо при существовании только одного из этих явлений - другое перестало бы иметь собственную суть, как сказано выше, его невозможно было бы отличить.
Я не вижу никакой проблемы в том, чтобы было только "ничего" (что равнозначно "ничего не было бы вообще"). Никакое "нечто" вообще не требуется. Просто ничего нет, и всё тут. В чем проблема вообще?
Именно поэтому невозможно доказать не-существование чего-либо.
Что значит "доказать"? Не-существование чего? Не-существования чего-то где-то иногда очень даже можно доказать. Например, можно посмотреть на пустой стакан, и это будет доказательством не-существования воды в этом стакане. Или это доказательством не является? Например, можно допустить, что у меня галлюцинации, и на самом-то деле вода там есть. Но тогда я и существование воды в стакане доказать не могу.
Может имеется в виду какое-то формальное доказательство в рамках некоторой строго аксиоматизированной формальной системы? Так ведь можно доказать не-существование чего-то, например есть доказательства не-существования самого большого простого числа (это напрямую следует из того, что простых чисел бесконечность).
Сейчас весь скрам превратился в полный buzzword. Например, extreme programming пропагандирует техническое совершенство — но где это совершенство?.. А скрам теперь просто buzzword, оно больше ничего не стоит. И даже Кен Швабер, изначальный создатель скрама, ушел из Scrum Alliance, потому что это все превратилось в армию консультантов: они прошли двухдневный курс и говорят, что знают, как наладить процессы в организации. Это стало религией, которую никто не знает, как практиковать.
Но мы можем делать лучше. Через какое-то время появился новый манифест. Манифест получился еще круче, он назывался «Manifesto for Software Craftsmanship».
Слово "скрам" превратилось в баззворд? Не проблема, мы придумаем вам новое слово "крафтсмен", которое тоже превратится в баззворд, и тогда мы придумаем еще какое-то слово...
Ну так это давно известно, такие аномалии выявлялись и ранее. Лекция поводу математики выборов и статистических аномалий некоторых голосованиях, проводившихся в РФ youtu.be/Q-RgoV_w8Vw которая была прочитана еще 22 декабря 2017 года. Там говорят про такие же аномалии с зубчиками на 80%, 85%, 90% и 95% — на этом моменте youtu.be/Q-RgoV_w8Vw?t=2529
Ну так зачем использовать термин "e-mail маркетинг", если то что вы сделали это именно что спам? Давайте я вам википедию процитирую
https://ru.wikipedia.org/wiki/Email-маркетинг#Заблуждения,_касающиеся_e-mail-маркетинга
Как я понял из статьи, никакого предварительного согласия ни с какими подписчиками у вас не было, следовательно вы занимались т.н. спамом.
Это так сейчас называют спам?
Эта статья напомнила мне одну статью с журнала "Наука и жизнь" https://www.nkj.ru/archive/articles/457/ :
В этом спинлоке
Количество итераций холостого цикла (в данном случае это 24 * 100) по каким критериям подбирать?
Скажите это квантовой физике
А с получившимся после дегалогенирования дифенилом что потом можно делать? Какой он будет чистоты? ПХБ находится при стандартном давлении и температуре в жидком состоянии, дифенил твердый. Дифенил наверняка будет в этом ПХБ растворяться в процессе дегалогенирования, а потом начнет выпадать в осадок. Так вот, не будет ли дифенил после коллоидной мельницы содержать в себе примеси ПХБ в опасных концентрациях?
А можно ли деактивировать хлордифенил карбидом кальция? Как вообще хлорорганика реагирует с карбидами щелочных и щелочноземельных металлов? Например, если хлорбензол с карбидом кальция: C6H5Cl + CaC2 нагревать, какие будут продукты? Можно ли так синтезировать C6H5-C≡C-C6H5?
Может и похоже чем-то, но нет, текстом стандарта это не является. Например вот фрагмент
6.1 Characters and integers
A char object may be used anywhere an int may be. In all cases the char is converted to an int by propagating its sign through the upper 8 bits of the resultant integer. This is consistent with the two’s complement representation used for both characters and integers. (However, the sign-propagation feature disappears in other implementations.)
В каких-то реализациях нет sign propagation при переводе из char в int? Очень интересный "стандарт". А про поведении при делении на ноль там что-нибудь вообще сказано в этом "стандарте"? Вот в K&R первой редакции https://ia801303.us.archive.org/1/items/TheCProgrammingLanguageFirstEdition/The%20C%20Programming%20Language%20First%20Edition%20%5BUA-07%5D.pdf про это сказано вот что:
The handling of overflow and divide check in expression evaluation is machine-dependent. All existing implementations of C ignore integer overflows; treatment of division by 0, and all floating-point exceptions, varies between machines, and is usually adjustable by a library function.
Machine-dependend уже предполагает, что есть не только лишь PDP-11. В K&R даже в первой редакции написано, что число бит в байте может быть разным, и тут уже явно упомянут не только PDP-11:
И что? Программы-то могут перестать работать, если в одной реализации программа работает нормально, а в другой получается Error? Вы жалуетесь, что программы на Си перестали из-за плохого стандарта работать, сломались работавшие когда-то сишные программы. Так вот, паскаль так тоже умеет. В одном компиляторе паскаля Integer один, и всё работает, в другом компиляторе паскаля Integer другой, и все сломалось. Паскаль должен умереть?
Что касается Си и Паскаля, то они достаточно легко ложится на фон-неймановские архитектуры, можно код функций перевести в код на ассемблере, при вызове функций, адрес возврата (место, откуда функция была вызвана) записывается в стек. Функции в процессе работы выделяют себе место в стеке под локальные переменные, есть передача аргументов в эти функции, для этого есть определенные соглашения вызовов, в адресном пространстве процесса еще есть область для глобальных и статических переменных. И эти языки явно делали с оглядкой на то, чтобы их было удобно компилировать. А некоторые языки на это так просто не натягиваются, например Prolog. И язык Prolog работает на другом уровне абстракций. Так понятней?
Его еще в первой редакции "The C programming language" в 1978 году начали от PDP-11 отвязывать, разрешив разное количество бит под байт, и упомянув архитектуры, отличные от PDP-11. Уже тогда Си должен был умереть?
Еще раз. Критерием "баг это или не баг" я считаю статус в багзилле GCC. В багзилле GCC это подтвердили как баг - значит это баг GCC. Баги это по-вашему только те случаи, когда некое поведение компилятора не соответствует стандарту?
То и имею в виду, что допустим вместо C89 выпустили бы "Extended-C", а Си оставили б в состоянии на момет выхода K&R. Это было бы существено лучше, это бы что-то радикально изменило?
Не нравится официальный стандарт - изобретите свой стандарт и сделайте там так, как вам нравится. Есть достаточно много ответвлений от языка Си.
Совсем-совсем все, т.е. 100% программ вдруг стали неработающими? Неработающими с точки зрения стандарта C89? А с точки зрения K&R они точно все были работающими? В K&R например написано, что бит в байте может быть 8, а может быть больше чем 8 - если какая-то программа полагается на то, что байт 8-битный, она может не заработать на архитектуре с 9-битным байтом. Или наоборот, если предполагается, что байт 9-битный, программа с 8-битным байтом может не работать корректно.
А какое это имеет отношение к "уровневости"? В Си кстати тоже размер int не указан, получается что он в вашей классификации язык высокого уровня? Вот в Java размер типа int как раз указан, выходит что Java это язык низкого уровня? https://docs.oracle.com/javase/specs/jls/se17/html/jls-4.html#jls-4.2 : The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units (§3.1).
Это не отменяет того факта, что программы на языке Паскаль могут перестать работать из-за того, что тип Integer вдруг стал другим, и не вмещает в себя нужный диапазон. Так что же получается, "Паскаль должен умереть"?
Где в стандарте языка Си написано, что Си это язык низкого уровня?
Нигде. Вполне можно интерпретировать Си, впрочем как и Паскаль. Впрочем, как и ассемблер x86. Я о том, что Си и Паскаль можно компилировать в достаточно эффективный машинный код для фон-неймановских архитектур.
А для языка низкого уровня не это безразлично? Писать интерпретаторы ассемблера незаконно? Что значит "для языка безразлично", у него какое-то свое мнение есть? Что вообще такое язык высокого и язык низкого уровня? Я язык Си не считаю языком низкого уровня, язык низкого уровня для меня это ассемблер, машинный код.
Багом это является по причине того, что в багзилле GCC признали, что это баг.
Т.е. надо было ничего в Си не менять, а создать новый язык, и было бы всем счастье? Ну допустим не меняли бы они ничего, выпустили бы вместо C89 новый частично совместимый с Си язык, назвали бы его как "Extended-C" например, напихали бы туда этих оптимизаций через неопределеное поведение при стрикт-алиазинге и прочее, на что вы тут жалуетесь, старые программы портировали бы на этот "Extended-C" а сам исконно-посконный Си забросили бы, как забросили языки B и BCPL, и что бы от этого принципиально поменялось?
А в каких случаях проблем бы не было? Вот например в паскале у Integer какой размер в байтах? https://archive.org/download/iso-iec-7185-1990-Pascal/iso-iec-7185-1990-Pascal.pdf - попробуйте там что-нибудь найти про это. На 55 странице этого PDF файла есть упоминание про maxint, который (сюрприз!) implementation-defined. Если посмотреть сюда https://wiki.freepascal.org/Integer - тут сказано Typical sizes of integer generally are 16 bit (2 byte), 32 bit (4 byte) or 64 bit (8 byte) - отлично, т.е. если кто-то в своей программе на паскале предполагает, что Integer 32-битный, на паскале с 16-битным Integer его код корректно не заработает. А если бит не 8-битный? Какие компилируемые в машинный код языки программирования, сопоставимые по уровню абстракции с тем же Си или паскалем, могут работать на (т.е. компилироваться под) архитектурах с не 8-битным байтом, чтобы код при этом не нужно было переделывать? Может надо делать отдельный язык для архитектур с 8-битным байтом, отдельный для 9-битного байта, отдельный для 16-битного байта, отдельный язык для two's complement, отдельный для one's complement знаковых чисел, и так под каждую архитектуру делать язык с особым уникальным именем?
Сейчас уже сами архитектуры подстраивают под языки, например в ARM есть инструкции, добавленные специально для джаваскрипта https://stackoverflow.com/questions/50966676/why-do-arm-chips-have-an-instruction-with-javascript-in-the-name-fjcvtzs
И специально для Си тоже добавляли инструкции чтобы код нормально работал http://c-faq.com/null/machexamp.html
The Prime 50 series used segment 07777, offset 0 for the null pointer, at least for PL/I. Later models used segment 0, offset 0 for null pointers in C, necessitating new instructions such as TCNP (Test C Null Pointer), evidently as a sop to [footnote] all the extant poorly-written C code which made incorrect assumptions.
Ну ок, значит не -nostdlib а какой-то другой флаг не сработал. Я просто привел цитату из багзиллы GCC.
Багом GCC является то, что использование некоторых флагов не позволяет эту оптимизацию отключить. То, что по стандарту (т.е. не используя специальных опций компилятора) нельзя написать свою реализацию memcpy, не является серьезной проблемой языка Си, т.к. во-первых такие функции не надо каждый день писать и во-вторых, это решается специальными флагами компилятора. Серьезных проблем в Си хватает, но это не одна из них
Под который нужно было бы переписывать весь старый код? А кто сказал, что такой язык никто не сделал? Вот D например есть. Или Rust.
Почему не сделали совместимый с Си язык, назвав его по-другому? Тоже сделали, называется он "C++", есть еще "Obj-C". Хотя насчет прекрасности я б тут поспорил.
Потому что под Си написано много кода, и его хотелось бы не переписывать, а дорабатывать. Введение в заблуждение в чем заключается? Си времен K&R был хорошим, а потом стал плохим? Вот например вы ругаете правила сравнения указателей:
Только вот это было еще в K&R, даже можно найти архивы ньюзгрупп, где обсуждалось еще в 1988 году https://compilers.iecc.com/comparch/article/88-07-002
>K&R 1, page 98:
>"But all bets are off if you do arithmetic or comparisons with pointers
>pointing to different arrays. If you're lucky, you'll get obvious
>nonsense on all machines. If you're unlucky, your code will work on one
>machine but collapse mysteriously on another."
Скорее так: если нужно реализовывать memcpy и прочие функции из стандартной библиотеки Си, нужно использовать специальные флаги компилятора или прагмы, не дающие компилятору соптимизировать это в рекурсию. Программисты редко когда свой memcpy реализовывают, так что это не то чтобы большая проблема.
Потому что см. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56888#c12 :
Now, if this replacement still happens when you compile with -nostdlib, that would be a bug since it becomes legal code in that case.
Т.е. флаг -nostdlib по-идее должен это разрешать, а он не разрешает. Там советуют использовать опцию -fno-tree-loop-distribute-patterns
Можно использовать для таких функций
attribute ((optimize ("-fno-tree-loop-distribute-patterns")))
и тогда должно нормально компилироваться без рекурсий.Для переносимости и для более агрессивной оптимизации.
А где она разрешима? Кроме ассемблера, я не слышал о других языках, которые бы давали такой уровень контроля. Как такой язык должен выглядеть, если это будет не ассемблер?
Но вообще можно придумать некую специальную прагму, которая заставит всё тот же компилятор Си генерировать код зануления стекфрейма и регистров по выходу из функции.
Если размер байта больше 8 бит (такое вполне бывает и разрешено стандартом), ничего страшного не произойдет. Если хочется получить UB, лучше использовать макрос CHAR_BIT
Кстати, тут можно и unsigned int взять. Если unsigned int 32-битный, сдвиг единицы на 32 тоже будет UB.
Да, есть такой баг. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56888
Только вы определитесь, вы конкретный компилятор Си ругаете, ли сам Си?
А еще существует вероятность, что какие-то куски пароля останутся в каких-нибудь регистрах, как это проконтролировать? Может тогда на ассемблере писать, ну что уж точно ничего случайно не просочилось? И кстати пароли в открыдом виде не хранят, а хранят их хэши.
Кстати, по поводу хешей. Взять например SHA256Transform за авторством Aaron Gifford которое присутствует в OpenBSD например http://fxr.watson.org/fxr/source/crypto/sha2.c?v=OPENBSD#L309
Там есть такая замечательная строчка, как
a = b = c = d = e = f = g = h = T1 = 0;
, где все эти a b c d ... являются локальными переменными в этой функции. Что вообще автор хотел этим сказать? Видимо он хотел избежать утечки каких-то данных через стек, и даже возможно через регистры. Компилятор это зануление локалок конечно имеет право выкинуть, но ДОПУСТИМ он не выкинет их, и действительно занулит соответствующие регистры и стек. Только в стеке и в регистрах могут быть записаны какие-нибудь промежуточные результаты вычислений, а их как вообще занулить? Писать специализированный компилятор, который все использованные функцией адреса в стеке и все использованные регистры (кроме возвращаемого значения) забивает нулями?На это никто и ничто надежно ответить не может, да и к тому же ответа может просто не быть. Я знаю только то, что я ничего не знаю.
Мне из цитаты неясно, что такое "суть". Нужно определение слова "суть" в данном контексте.
Доказать не-существование чайника Рассела в определенном конкретном месте и в определенное время очень даже можно. Например, какой-нибудь телескоп доказывает через свои камеры, что в некоторой конечной области пространства сейчас никаких чайников нет. И космонавты в открытом космосе тоже доказывают, что мимо них чайники сейчас не пролетают. А доказать "вообще нигде во Вселенной нет ни одного чайника" будет уже затруднительно.
Кстати, а как бы вы доказывали, что между Землёй и Марсом вокруг Солнца вращается по крайней мере один чайник Рассела? Допустим, кто-то шутки ради действительно отправил на орбиту такой чайник, и его удалось увидеть на снимках с телескопа, но где гарантии, что снимки с телескопа не были специально подделаны какими-нибудь шутниками? А где гарантии, что всё это не ваш сон? Что будет считаться доказательством?
По каким причинам мы само наличие "ничто" принимаем за "1 единицу чего-то"? Оно же на то и "ничто", что его нет, так что никакой "1 единицы ничего" нет, и дальнейшие рассуждения смысла не имеют.
Наличие каких-либо законов физики нельзя строго доказать. Можно поставить счетное и конечное множество экспериментов, и на основе полученных данных можно построить некую физическую теорию, по которой можно было бы с какой-то точностью предсказывать "что будет, если ...".
Где (в чем) оно было? Или оно было "само в себе"? Что вообще означает "быть"? Откуда мы можем знать, что это "ничто" реально когда-то было? А что если "быть" вообще неприменимо к "ничто"?
ОК, допустим. И зачем понадобилось предполагать, что когда-то в самом начале было некое "ничто"?
Что значит "иметь в себе суть"? Что такое "суть"?
Пусть будет одно единственное "ничто", и никаких других "ничто" не будет. Почему должно быть проблемой то, что кто-то в рамках некоторой формальной системы что-то не может описать?
А если логика неправильная, и на самом деле существование "ничто" ни к какому существованию "нечто" не приводит? Что такое "нечто"? И кстати, какая логика, классическая или интуиционистская(нет закона исключённого третьего)? Или может какая-то своя? Есть еще многозначные логики, модальные логики и проч.
Откуда взялась уверенность, что используемая вами логика адекватно описывает предметную область, и дает верные выводы о сущности вещей, что что-то там существует если вот то существует? См. https://youtu.be/u1AyoXrXYe4?t=1263 (почему можно поставить под сомнение тезис, что 2*2=4)
Я не вижу никакой проблемы в том, чтобы было только "ничего" (что равнозначно "ничего не было бы вообще"). Никакое "нечто" вообще не требуется. Просто ничего нет, и всё тут. В чем проблема вообще?
Что значит "доказать"? Не-существование чего? Не-существования чего-то где-то иногда очень даже можно доказать. Например, можно посмотреть на пустой стакан, и это будет доказательством не-существования воды в этом стакане. Или это доказательством не является? Например, можно допустить, что у меня галлюцинации, и на самом-то деле вода там есть. Но тогда я и существование воды в стакане доказать не могу.
Может имеется в виду какое-то формальное доказательство в рамках некоторой строго аксиоматизированной формальной системы? Так ведь можно доказать не-существование чего-то, например есть доказательства не-существования самого большого простого числа (это напрямую следует из того, что простых чисел бесконечность).
Слово "скрам" превратилось в баззворд? Не проблема, мы придумаем вам новое слово "крафтсмен", которое тоже превратится в баззворд, и тогда мы придумаем еще какое-то слово...
А зачем смесь сразу из трех языков использовать? Если используется Rust, зачем тогда C++, почему не оставить C, Rust?
Можно перебирать разные UB, может какое-то еще подойдет