Алиасы столбцов определяют имена для выхода для SELECT.
Чтобы использовать их в самом предложении SELECT, вам необходимо добавить еще один слой косвенности:
SELECT c1 FROM (SELECT 42 AS c1)
Ну, сначала обратите внимание, что бросок явный запрос для преобразования значения одного типа к значению другого типа . Бросок будет также всегда производить новый объект, который является временным файлом, возвращенным оператором броска. Кастинг к ссылочному типу, однако, не создаст новый объект. Объекту, на который ссылается значение, дают иное толкование как ссылка другого типа.
Теперь к Вашему вопросу. Обратите внимание, что существует два главных типа преобразований:
-1
к неподписанному типизированному объекту, например. В некоторых случаях неправильное преобразование может привести к неопределенному поведению. При присвоении двойного большего, чем, что плавание может сохранить к плаванию, поведение не определяется. Позволяют нам посмотреть на Ваши броски:
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
unsigned int
. Если бы целое число было отрицательно, значение в основном перенесло бы максимальное значение неподписанного интервала (см. 4.7/2). 10.123
является усеченным к 10. Здесь, это делает причина, потерянная информации, очевидно. Как 10 вписывается в неподписанный интервал, поведение определяется. char*
. Но давайте проигнорируем это здесь. (см. здесь ). Что еще более важно, что действительно происходит, если Вы бросаете к неподписанному типу? На самом деле результат этого является неуказанным на [1 124] 5.2.10/7 (обратите внимание, что семантика того броска совпадает с использованием reinterpret_cast в этом случае, так как это - единственная способность броска C++ сделать это): указатель А на объект может быть явно преобразован в указатель на объект другого типа. За исключением того, что, преобразовывая rvalue типа “pointer к T1” к типу "указатель на T2" (где T1 и T2 являются типами объектов и где требования выравнивания T2 не более строги, чем те из T1) и назад к его исходному типу приводит к исходному значению указателя, результат такого преобразования указателя является неуказанным.
, Таким образом, Вы только в безопасности использовать указатель после того, как Вы вспомните char *
снова.
Броски имеют в виду разные вещи в зависимости от того, каковы они. Они могут просто быть переименованиями типа данных без изменения в представленных битах (большинство бросков между целочисленными типами, и указатели похожи на это), или преобразования, которые даже не сохраняют длину (такой как между двойным и международным на большинстве компиляторов). Во многих случаях значение броска является просто неуказанным, означая, что компилятор должен сделать что-то разумное, но не должен документировать точно что.
бросок А не должен даже приводить к применимому значению. Что-то как
char * cp;
float * fp;
cp = malloc(100);
fp = (float *)(cp + 1);
почти наверняка приведет к неправильно выровненному указателю на плавание, которое разрушит программу в некоторых системах, если программа попытается использовать его.
Два броска C-стиля в Вашем примере являются различными видами броска. В C++ Вы обычно писали бы им
unsigned int uf1 = static_cast<unsigned int>(fl);
и
unsigned char* up = reinterpret_cast<unsigned char*>(p);
, первое выполняет арифметический бросок, который усекает число с плавающей точкой, таким образом, существует потеря данных.
второе не вносит изменений в данные - они просто дают компилятору команду рассматривать указатель как другой тип. Необходимо соблюдать осторожность об этом виде броска: это может быть очень опасно.
"Введите" в C, и C++ является свойством, присвоенным переменным, когда они обрабатываются в компиляторе. Свойство больше не существует во времени выполнения, за исключением виртуальных функций/RTTI в C++.
компилятор использует тип переменных для определения большого количества вещей. Например, в присвоении плавания к интервалу, это будет знать, что должно преобразовать. Оба типа - вероятно, 32 бита, но с различными значениями. Вероятно, что ЦП имеет инструкцию, но иначе компилятор знал бы для вызова функции преобразования. Т.е. & __stack[4] = float_to_int_bits(& __stack[0])
преобразование из символа* к неподписанному символу* даже simpeler. Это - просто различная маркировка. На разрядном уровне, p и идентичны. Компилятор просто должен помнить, что *p требует расширения знака, в то время как *не делает.