Точно ли сказать, что C является частично типобезопасным языком?

#c

#c

Вопрос:

В C есть некоторые функции, которые являются типобезопасными, а некоторые другие функции — нет.

Пример безопасности типов C :

 char c = 'a';
int *p = amp;c;    // this is not allowed (compiler error)
  

Пример отсутствия безопасности типов в C :

 int *p;        // I don't have to initialize p, and so it will have some junk/random value
*p = 12345;    // this will probably lead to segmentation fault!
  

Я прочитал в нескольких статьях, что C не является типобезопасным языком. Могу ли я считать его не типобезопасным языком или точнее сказать, что это частично типобезопасный язык?

Комментарии:

1. Я бы сказал, что ваш второй пример не имеет ничего общего с безопасностью типов.

2. Это просто старое неопределенное поведение.

3. C — это типобезопасный язык, не смешивайте понятия. Безопасность типов включает типы, разыменование недопустимого указателя не имеет ничего общего с типами.

4. @Hurkyl если в моем втором примере я присвоил p int значение (например: int *p = 12345 ) и компилятор разрешил это, считается ли это нарушением безопасности типов?

5. @Tom Дело в том, что ты никогда не говорил, что это int . Это просто десятичное целое число, которое может быть любого типа.

Ответ №1:

Разумно и практически осмысленно сказать, что C является частично типобезопасным языком.

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

В частности, C получил разложение массива на указатель из C. В C он не является типобезопасным, поскольку допускает неявное преобразование из массива Derived в указатель на Base , который, в свою очередь, может быть проиндексирован, но с неопределенным поведением.

Ответ №2:

Приведенный вами пример вообще не нарушает «безопасность типов». Здесь:

Пример отсутствия безопасности типов в C :

 int *p;     // I don't have to initialize p, and so it will have some junk/random value
*p = 12345; // this will probably lead to segmentation fault!
  

В этом примере *p это an int , и вы присваиваете ему номер 12345 , который также является an int .

Компилятор не позволяет вам нарушать систему типов, потому что вы присваиваете одно int другому int .

Тот факт, что указатель, который вы разыменовываете, чтобы перейти к одному из ваших int s, не инициализирован, вызывает потенциальный сбой, но это не имеет ничего общего с безопасностью типов.

Это не приведет к сбою:

 int* p = new int;
*p = 12345;
  

Здесь вы пишете int ( 12345 ) в другой int ( *p ), но на этот раз int вы пишете в ( *p ) на самом деле существует.

Компилятор не проверяет безопасность типов, а целостность указателя.

Комментарии:

1. У меня есть еще один вопрос о безопасности типов, если вы не возражаете, если у меня есть int переменная ( int i = 12345 ) , а затем я попытался обработать эту int переменную как указатель на функцию ( i() ) , теперь компилятор, конечно, помешает мне это сделать. Это предотвращение из-за того, что я нарушил безопасность типов, когда пытался обрабатывать i как указатель на функцию, или это не относится к безопасности типов?

2. @Tom Да, это нарушение типа. Тип определяет, какие операции могут выполняться над объектом.