Search
Write a publication
Pull to refresh
37
0
Send message

Это прекрасно. Базовые факты о поведении С++-style casts тут все хорошо известны.


Как это относится к теме более строго контроля типов? Контроль типов в языке — это именно контроль неявных преобразований. Явные преобразования (касты) к этой теме не относятся.


В любом случае, "созвездие" С++-style casts позволяет вам сделать все, что угодно (не говоря уже о том, что C-style cast никто в С++ не запрещал).

Вы по прежнему не понимаете, о чем речь. Конструкции 1-5 в таком чистом виде не имеют никакого применения. Они лишь демонстрируют важные фундаментальные факты и языке. На эти фундаментальные факты опираются все программы на С без исключения. Это не "схемы", удачные или неудачные, это иллюстрации Закона Ома.

Нет. Это популярное наивное заблуждение.


Во-первых, это было бы справедливо только в отношении компиляторов, которые строго и аккуратно разделяют warnings и errors про указанному вами принципу. Таких компиляторов С просто нет.


Например, при компиляции в GCC в умолчательной конфигурации огромное число warnings — это именно грубейше некорректные языковые конструкции, которые GCC просто так решил отрапортовать как warnings (ради совместимости с каким-нибудь старинным кодом).


Попыткой достижения строгого деления на warnings и errors в GCC является флаг -pedantic-errors, но и он еще не идеален.


Во-вторых, формально придраться к GCC тут нельзя, ибо в С нет понятия warnings и errors. Есть только понятие diagniostic message. Задача компилятора — сказать хоть что-то. А уж разбираться затем в формальной корректности конструкции, листая стандарт языка — это ваша задача.

Да, перечисления — хороший пример, в дополнение к void *. Еще что нибудь? (Явные касты же — не по теме. Явные касты — это средства обхода контроля типов.)


Заявления о более либеральном контроле типов в С как правило базируются на "пионэрских" верованиях, что С якобы разрешает такие вещи, как int *p = 123 или игнорирование const-корректности (см. яркий образчик такого заявления выше). В качестве доказательства приводится тот факт, что чей-то уютненький компилерчик выдает на это "всего лишь warning".


Понятно, что к реальности такие заявления никакого отношения не имеют.

Во-первых, ни в коем случае. Язык С — это язык не ниже С99. Формально С11 — нынешний стандарт, но его можно назвать достаточно минорной модификацией С99 (ака "финтифлюшками"). Но С99 обсуждению не подлежит.


Во-вторых, как уже говорил выше, контроль типов всегда был строго идентичным в С и С++, за исключением возможности неявной конверсии из void * в С. Да, современный С++ усилил контроль за конверсиями (за счет запрета narrowing conversions в ряде контекстов), но это ведь не то, что вы имели в виду, правда?

Во-первых, это оголтелое вранье. Никакого неопределенного поведения в первом и втором примерах нет. Третий и четвертый смогут содержать его потенциально, но речь там идет не о том. Явному неопределенному поведению посвящен только пятый пример.


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

Это во-первых. А во-вторых, на тот язык, который Денис Ритчи разработал «для замены ассемблера», можно взглянуть в известном документе самого Дениса Ритчи: «C Reference Manual» (CRM)

http://www.math.utah.edu/computing/compilers/c/Ritchie-CReferenceManual.pdf

В этом языке действительно чувствуется сильное влияние ассемблера. Однако все это было выкинуто из языка очень быстро: CRM C очень сильно отличается от K&R C, не говоря уже о ANSI C, не говоря уже о современном С.
Это не более чем частный случай проявления неопределенного поведения.
Напоминаю, что мы говорим про язык С.

Во-первых, язык С для компилятора GCC, который скрывается за ideone, начинается с флагов `-std=...` и `-pedantic-errors`. Без этих флагов компилятор GCC является компилятором развеселого студенческого языка для пивных вечеринок, никакого отношения к С не имеющего.

Во-вторых, фронтэнд ideone известен грубой фильтрацией диагностических сообщений, по каковой причине для демонстрации свойств языка всерьез рассматриваться не может.

Научитесь пользоваться хотя бы coliru

http://coliru.stacked-crooked.com/a/aef58ce98b518d02

Существуют и другие уважаемые онлайновые фронтэнды. Но не ideone.
В моем комментарии нет ни слова о том, что программы «должны опираться на неопределенное поведение».
Это откуда? В языке С никогда не было неявного приведения `const T*` к `T*`. Разумеется с того момента, комитет X3J11 ввел в язык С `const`.
Видимо поэтому вам никогда не доведется принимать такие решения.

Это не трюки, а фундаментальные свойства С, как платформы. Это атомы, из которых состоит С. Абсолютно любая программа на языке С опирается на эти «трюки».

Надо заметить, что Брайан Керниган не имеет никакого отношения к разработке языка С вообще, как он сам не раз заявлял. Как активный участник разработки языка В (предшественника С) он участвовал в подготовке книги, но не более того.

Язык С практически ничем не отличается от языка С++ в области строгости типизации. Единственное отличие, которое навскидку приходит в голову — это возможность неявной конверсии void * в другие объектные типы указателей в языке С. Все.


Так о какой строгой типизации вы ведете речь?

Очень зря. Свойства uint8_t (если таковой тип предоставляется реализацией) четко оговорены спецификацией языка и никакой неоднозначности не допускают. "Зацикленное" (модульное) поведение беззнаковых типов — очень полезная фича языка, пользоваться которой можно и нужно. Поэтому ваше "чем больше узнаю", похоже, привело лишь к тому, что с водой вы выплеснули и ребенка.

Перед вами — абстрактные дистилированные примеры, иллюстрирующие фундаментальные свойства языка. Как таковые, эти свойства языка используются в абсолютно всех программах на языке С без исключения.

Во-первых, при чем здеcь "IDE" не совсем ясно. Все таки это определяется компилятором, а не IDE.


Во-вторых, вы фантазируете. В CodeWarrior нет и никогда не было требования "объявлять все переменные строго в начале функции".

В языке С нет и никогда не было требования объявлять переменные строго в начале функции. Откуда вы это вязли?


Даже K&R С (не говоря уже о стандартизованном С) переменные всегда объявлялись в начале блока, а не в начале функции. Однако и это — далекое прошлое. В языке С переменные уже 17 лет как можно объявлять где угодно.


Другими словами вас "жутко выбешивает" вам же выдуманная чепуха, не имеющая никакого отношения к реальности.

"Существовали платформы где он был по 6 бит (помните триграфы?)..." — это замечание, конечно, совершенно "мимо кассы". Особенности символьного набора (execution character set) конкретной платформы формально влияют на размет типа 'char' только тем, что обязаны в него помещаться. Не более того.


Даже в стариннейшем "C Reference Manual" тип 'char' уже постулировался, как знаковый 8-битный тип в формате 2's-complement. А дальше его спецификация становилась лишь еще более абстрактной и свободной.

Ширина типа 'char' — то есть количество значащих битов в нем — не оговаривается стандартом языка. Результат же 'sizeof(char)' — гарантированно 1. То есть тип 'char' — это единица измерения размеров всех остальных типов, это «байт» в понимании языка С. Однако диапазон значений этого типа не фиксирован.

Information

Rating
Does not participate
Registered
Activity