Каково точное значение «безопасность типов» в C ++?

0

Согласно этому сайту:

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

int *x = malloc(sizeof(int) * 10);

но он не будет компилироваться в C++.

Объяснение самого Бьярна Страустрапа заключается в том, что это не безопасный тип. Это означает, что вы можете иметь void* который указывает на что-либо вообще, и если вы затем присвоите адрес, хранящийся в этом void *, другому указателю другого типа, в нем нет никакого предупреждения.

Рассмотрим следующее:

int an_int;
void *void_pointer = &an_int;
double *double_ptr = void_pointer;
*double_ptr = 5;
cout<<an_int<<endl;

Когда вы назначаете *double_ptr значение 5, оно записывает 8 байтов памяти, но целочисленная переменная an_int составляет всего 4 байта. Поэтому, когда вы печатаете значение переменной an_int, вывод будет равен 0, поскольку в соответствии с 4 байтами компилятор выбирает младшие значащие биты 5 (5.000..), которые an_int 0.

В C++ принудительное отбрасывание из указателя пустоты заставляет программиста обратить внимание на эти вещи. Таким образом, в этом языке неявно вводится преобразование из void * что позволяет повысить безопасность типов.

но я в буквальном смысле сбив с толку, когда я наложил void * на double * в этом примере, например:

int an_int;
void *void_pointer = &an_int;
double *double_ptr = (double *)void_pointer;
*double_ptr = 5;
cout<<an_int<<endl;

Выход будет таким же, как и 0.

Итак, какая здесь роль-безопасность? и что именно Bjarne Stroustrup объяснил о типе безопасности?

  • 2
    ... и тогда как в c вам не нужно было спрашивать, в c ++ вы теперь вынуждены спрашивать => больше безопасности типов
  • 0
    но в примере, который я дал, приведение типов не играет никакой роли? так когда приведение типов полезно?
Теги:
casting

3 ответа

4

"Тип-безопасность" означает, что компилятор не позволит вам использовать не соответствующие типы для операций, если только вы явно не просите об этом (например, выполните тип c-style или c++ reinterpret_cast<>, в вашем примере).

  • 0
    но в примере, который я дал, приведение типов не играет никакой роли? так когда приведение типов полезно?
  • 0
    @VikasVerma: когда у вас есть один тип ( char ) и вы хотите другой ( int ). Или у вас есть char* и вы хотите std::string .
Показать ещё 5 комментариев
0

Сильный статический тип безопасности является основным элементом C++. Это в основном означает, что вы можете передавать информацию только между совместимыми типами, а самый совместимый тип любого типа - это самый тип. Эта идея обогащена способами использования базовых типов с производным типом той же иерархии классов и т.д. И т.д. До большой сложности и логической силы. Существует также основная идея, что C++ остается максимально совместимым с C. Из этого следует, что void * совместим с любым типом указателя. Обычно его лучше избегать, поскольку в C++ всегда есть лучший дизайн.

-2

Я не могу устоять. "Тип безопасности" - маркетинговый кляп C++. Рассмотрим следующий код:

#include <stdio.h>

class A {
public:
    int x;
};

class B : public A {
  // B is derived from A, which makes
  // B "compatible" to A
public:
  // B adds a 2nd member, which means
  // that B is "bigger" than A
    int y;
};

int main()
{
    B a1[10];
    A *a2;
    a2 = a1; // this is legal :-( 
    a1[0].x=1;
    a1[0].y=1;
    a2[0].x=2;
    a2[1].x=3; // Upps: this probably overwrites a1[0].y
    printf("a1[0].x = %d\n",a1[0].x);
    printf("a1[0].y = %d\n",a1[0].y);
    return 0;
}

Скомпилируйте это с помощью "g++ -Wall -патентный -fstrict-aliasing" или любые другие варианты, которые вы найдете. Я, по крайней мере, не смог выпустить предупреждение. В приведенном выше коде не используются кавычки типов, и вы все равно получаете код, который ломается или, по крайней мере, совершенно не делает того, что вы думаете, что он должен делать.

Гуру C++ может теперь рекомендовать использовать "вектор" или что-то еще. Но это не главное. Дело в том, что C++ вообще не защищен типом.

EDIT: Поскольку это, кажется, запутывает, вот объяснение того, что является источником проблемы.

Поскольку C++ является объектно-ориентированным, класс "B" совместим с "классом A" (поскольку "класс B" является производным от "класса A"). Это означает, что вы можете использовать объект класса "В" в месте, где требуется объект класса "А". Это, в свою очередь, означает, что вы можете использовать указатель класса B * в месте, где требуется указатель класса A *.

Теперь проблема в том, что C++ допускает арифметику указателя (из-за этого на C). Арифметика указателя довольно плохо взаимодействует с наследованием и совместимыми типами. Потому что в приведенном выше примере "a2 + 1" (a2 - это "указатель класса A *") приводит к другому адресу, чем "a1 + 1" (a1 является указателем "класс B *").

Итак, подведем итог: C++ считает типа "класса B *", чтобы быть совместимым типа "класса А *", но, к сожалению, эти типы не совместимы при их использовании для арифметики с указателями.

  • 0
    Это все совершенно неправильно! @IngoBlackman 'Суть в том, что C ++ вообще не безопасен для типов.' Я сомневаюсь, что серьезно! Если вы обнаружите случаи, вы несете ответственность за нарушение безопасности типов и призыв к неопределенному поведению. Можете ли вы уточнить и показать больше доказательств, помимо простого показа неопределенного поведения, с использованием неверно приведенных необработанных указателей ??
  • 0
    И кстати, порядочные компиляторы способны обнаруживать несовпадение printf() форматирование спецификаторов против типов параметров вы передаете и дать вам хотя бы предупреждение за что!
Показать ещё 11 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню