Это приведение типа - это форма преобразования типа операнда (problem3
в вашем примере) в другой тип.
В C (и в C ++, когда используется приведение в стиле C), приведение может выполнять одно из следующих действий:
- ничего не делать, кроме изменения типа чего-либо без изменения формы данных. Например, когда вы приводите указатель на int.
- выполнить преобразование как часть операции приведения. Например, при приведении числа с плавающей точкой к int данные фактически преобразуются из формы, используемой для представления значений с плавающей запятой (обычно в форме экспоненты / мантиссы), в простое старое целое число (с потерей любой дробной части)
Поскольку различные формы приведения могут быть запутанными или неясными относительно того, что происходит (или должно было произойти), C ++ добавил несколько определенных операторов приведения:
reinterpret_cast<>()
, что соответствует первой форме, описанной выше
static_cast<>()
, что соответствует второй форме (даже если преобразование не приводит к изменению внутреннего формата данных)
const_cast<>()
, который представляет собой особый случай приведения, который может удалить квалификаторы const
или volatile
, которые могут быть применены к объекту
dynamic_cast<>()
, который является совершенно новым для C ++ и не имеет аналогичных функций в C. Этот оператор используется для безопасного «понижения» базового типа объекта до одного из его производных типов.
Поскольку они по своей природе опасны, броски обычно считаются плохой формой. Когда вы выполняете операцию приведения, вы подрываете способность компилятора выполнять проверку типов. Однако бывают случаи, когда это может быть необходимо или очень полезно, и вы увидите, что это часто используется в коде C.
В вашем примере problem3
является указателем на функцию, и приведение «конвертирует» адрес этой функции в тип int. Затем он сохраняет этот адрес as-int в массиве, но на самом деле один элемент массива за концом массива (который является нет-нет). На многих платформах этот недопустимый элемент массива находится там, где хранится адрес возврата для функции, поэтому, когда произойдет возврат функции problem3()
, она вернется к себе и снова запустится (ad-infinitum - своего рода).
Это в конечном итоге приведет к опустошению стека, потому что новый, «взломанный» прогон problem3()
не будет иметь вызова функции, который поместит адрес возврата в стек - он просто уничтожит все остальное, что было в стеке раньше это и return
к себе снова, повторяя процесс, пока стек не опустошится, что, вероятно, вызовет исключение процессора.