С ++ считается слабо типизированным? Зачем?

Я всегда считал С ++ одним из наиболее строго типизированных языков.
Поэтому я был шокирован, увидев, что в Таблице 3 этой статьи говорится, что C++ слабо типизирован.

По-видимому,

C и C++ считаются слабо типизированными, поскольку из-за приведения типов можно интерпретировать поле структуры, которое было целым числом, как указатель.

Имеет ли значение только приведение типов? Разве явность таких приведений не имеет значения?

В более общем смысле, действительно ли общепринято, что C++ слабо типизирован? Зачем?

6 ответов

Решение

Эта статья сначала утверждает:

Напротив, язык слабо типизирован, если путаница типов может происходить тихо (незамеченной) и в конечном итоге приводить к ошибкам, которые трудно локализовать.

А потом утверждает:

Кроме того, C и C++ считаются слабо типизированными, поскольку из-за приведения типов можно интерпретировать поле структуры, которое было целым числом, как указатель.

Это кажется мне противоречием. В C и C++ путаница типов, которая может возникнуть в результате приведения типов, не будет происходить молча - это приведение! Это не демонстрирует, что какой-либо из этих языков является слабо типизированным, по крайней мере, не по определению в этой статье.

Тем не менее, согласно определению в статье, C и C++ все еще можно считать слабо типизированными. Как уже отмечалось в комментариях к этому вопросу, существуют случаи, когда язык поддерживает неявные преобразования типов. Многие типы могут быть неявно преобразованы в bool, буквальный ноль типа int может быть тихо преобразован в любой тип указателя, есть преобразования между целыми числами разных размеров и т. д., поэтому это кажется хорошей причиной для того, чтобы рассматривать C и C++ в слабой типизации для целей статьи.

Для C (но не C++) есть также более опасные неявные преобразования, о которых стоит упомянуть:

int main() {
  int i = 0;
  void *v = &i;
  char *c = v;
  return *c;
}

Для целей статьи, это, безусловно, следует считать слабым шрифтом. Переинтерпретация битов происходит бесшумно, и ее можно значительно ухудшить, изменив ее на использование совершенно не связанных типов, которая имеет тихое неопределенное поведение, которое обычно имеет тот же эффект, что и реинтерпретация битов, но взрывается таинственными, но иногда забавными способами, когда оптимизация включена,

В целом, однако, я думаю, что не существует фиксированного определения "строго типизированный" и "слабо типизированный". Существуют различные оценки, язык, который строго типизирован по сравнению со сборкой, может быть слабо типизирован по сравнению с Паскалем. Чтобы определить, является ли C или C++ слабо типизированным, вы должны сначала спросить, что вы хотите, чтобы означало слабо типизированное.

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

Из того, что я могу сказать, люди обычно используют "слабо типизированный" как уменьшительно-уничижительный термин, который означает "мне не нравится понятие типов в этом языке". Это своего рода аргумент ad hominem (или, скорее, аргумент ad linguam) для тех, кто не может выдвинуть профессиональные или технические аргументы против конкретного языка.

Термин "строго типизированный" также имеет несколько иные толкования; по моему опыту общепринятое значение - "компилятор генерирует ошибки, если типы не совпадают". Другая интерпретация заключается в том, что "нет или мало неявных преобразований". Исходя из этого, C++ можно считать строго типизированным языком, и чаще всего его считают таковым. Я бы сказал, что общее мнение о C++ заключается в том, что это строго типизированный язык.

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

Кроме того, есть некоторые программисты, особенно начинающие, которые не знакомы с более чем несколькими языками, которые не собираются или не могут проводить различие между "строгим" и "статическим", "свободным" и "динамическим", и объединить два - иначе ортогональных - понятия, основываясь на их ограниченном опыте (обычно, например, корреляция динамичности и свободной типизации в популярных языках сценариев).

В действительности, части C++ (виртуальные вызовы) налагают требование, чтобы система типов была частично динамичной, но другие вещи в стандарте требуют, чтобы она была строгой. Опять же, это не проблема, так как это ортогональные понятия.

Подводя итог: возможно, ни один язык полностью не вписывается в ту или иную категорию, но мы можем сказать, какое именно свойство данного языка доминирует. В C++ строгость определенно доминирует.

Что ж, поскольку создатель C++, Бьярн Страуструп, говорит в The C++ Programming Language (4-е издание), что язык строго типизирован, я бы поверил ему на слово:

Программирование на C++ основано на строгой статической проверке типов, и большинство методов нацелены на достижение высокого уровня абстракции и прямого представления идей программиста. Обычно это можно сделать без ущерба для времени выполнения и экономии пространства по сравнению с методами нижнего уровня. Чтобы воспользоваться преимуществами C++, программисты, переходящие к нему с другого языка, должны изучить и усвоить идиоматический стиль и технику программирования C++. То же самое относится и к программистам, привыкшим к более ранним и менее выразительным версиям C++.

В этой видеолекции 1994 года он также заявляет, что слабая система типов C его действительно беспокоила, и именно поэтому он сделал C++ строго типизированным: Дизайн C++, лекция Бьярна Страуструпа

Напротив, язык слабо типизирован, если путаница типов может происходить тихо (незамеченной) и в конечном итоге приводить к ошибкам, которые трудно локализовать.

Ну, это может произойти в C++, например:

#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
#include <limits>

void f(char n) { std::cout << "f(char)\n"; }
void f(int n) { std::cout << "f(int)\n"; }
void g(int n) { std::cout << "f(int)\n"; }

int main()
{
    float fl = M_PI;   // silent conversion to float may lose precision

    f(8 + '0'); // potentially unintended treatment as int

    unsigned n = std::numeric_limits<unsigned>::max();
    g(n);  // potentially unintended treatment as int
}

Кроме того, C и C++ считаются слабо типизированными, поскольку из-за приведения типов можно интерпретировать поле структуры, которое было целым числом, как указатель.

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

Имеет ли значение только приведение типов? Разве явность таких приведений не имеет значения?

Ясность является решающим фактором ИМХО. Позволить программисту переопределить знание типов компилятором - это одна из "мощных" возможностей C++, а не некоторая слабость. Это не склонно к случайному использованию.

В более общем смысле, действительно ли общепринято, что C++ слабо типизирован? Зачем?

Нет - я не думаю, что это принято. C++ достаточно строго типизирован, и способы, которыми он был снисходительным, который исторически вызывал проблемы, были отменены, такие как неявное приведение из void* к другим типам указателей, и более точный контроль с explicit операторы и конструкторы.

В общем:

Вокруг темы неразбериха. Некоторые термины различаются от книги к книге (не считая интернета), а некоторые могли меняться с течением времени.

Ниже то, что я понял из книги "Разработка компилятора" (2-е издание).


1. Нетипизированные языки

Языки, у которых вообще нет типов, как, например, в ассемблере.


2. Языки со слабой типизацией:

Языки с плохой системой типов . Определение здесь намеренно двусмысленно.


3. Языки со строгой типизацией:

Языки, в которых каждое выражение имеет однозначный тип. PL можно дополнительно разделить на:

  • A. Статически типизированный: когда каждому выражению присваивается тип во время компиляции.
  • B. Динамически типизированный: когда некоторые выражения могут быть введены только во время выполнения.


Что такое С++ тогда?

Ну, это точно типизировано. И в основном он статически типизирован. Но поскольку некоторые выражения можно набирать только во время выполнения, я думаю, они подпадают под категорию 3.B.

PS1: Примечание из книги:

Строго типизированный язык, который можно статически проверять, может быть реализован (по какой-то причине) только с проверкой во время выполнения.

PS2: Третье издание недавно было выпущено

Я не владею им, поэтому я не знаю, изменилось ли что-то в этом отношении. Но в целом глава «Семантический анализ» изменила и название, и порядок в оглавлении.

Позвольте мне привести простой пример:

 if ( a + b )

C / C + = позволяет неявное преобразование из числа с плавающей точкой в ​​int в логическое значение.

Язык со строгой типизацией не допускает такого неявного преобразования.

Другие вопросы по тегам