Ответ 1
Хорошо, сначала обратите внимание, что приведение - это явный запрос на преобразование значения одного типа в значение другого типа. Приведение также всегда будет создавать новый объект, который временно возвращается оператором литья. Однако приведение к ссылочному типу не создаст новый объект. Объект, на который ссылается значение, переинтерпретируется как ссылка другого типа.
Теперь на ваш вопрос. Обратите внимание, что есть два основных типа преобразований:
- Акции: этот тип можно подумать о том, чтобы лить от более узкого типа к более широкому типу. Кастинг от char до int, от short до int, float to double - все рекламные акции.
- Конверсии: они позволяют использовать листинг от long до int, int до unsigned int и т.д. Они могут в принципе вызывать потерю информации. Существуют правила для того, что произойдет, если вы присвойте
-1
неподписанному типизированному объекту, например. В некоторых случаях неправильное преобразование может привести к поведению undefined. Если вы присваиваете двойной размер, превышающий то, что float может хранить для float, поведение не определяется.
Посмотрите на свои роли:
int i = 10;
unsigned int k = (unsigned int) i; // :1
float fl = 10.123;
unsigned int ufl = (unsigned int) fl; // :2
char *p = "Stackoverflow Rocks";
unsigned char *up = (unsigned char *) p; // :3
- Этот приведение вызывает преобразование. Потеря данных не происходит, так как 10 гарантируется сохранение
unsigned int
. Если целое число было отрицательным, значение будет в основном обтекать максимальное значение unsigned int (см. 4.7/2). - Значение
10.123
усечено до 10. Здесь оно, очевидно, вызывает потерю информации. Поскольку 10 вписывается в unsigned int, поведение определяется. - На самом деле это требует большего внимания. Во-первых, устаревшее преобразование из строкового литерала в
char*
. Но не будем игнорировать это здесь. (см. здесь). Что еще более важно, что происходит, если вы применяете неподписанный тип? Фактически, результат этого не указан в 5.2.10/7 (обратите внимание, что семантика этого акта такая же, как использование reinterpret_cast в этом случае, поскольку это единственный С++-транслятор, способный сделать это ):
Указатель на объект может быть явно преобразован в указатель на объект разного типа. За исключением того, что преобразование rvalue типа "указатель на T1" в тип "указатель на T2" (где T1 и T2 являются типами объектов и где требования к выравниванию T2 не более строгие, чем требования T1) и обратно к исходному типу исходное значение указателя, результат такого преобразования указателя не указан.
Таким образом, вы можете использовать указатель только после того, как снова вернетесь к char *
.