, от себя ещё добавлю разницу между (float) и const_cast<float> применительно к константным объектам, которую ощутил на собственной шкуре.
Однажды я писал под одну PDA платформу. На той платформе, как практически на всех ранних PDA платформах, вся память делилась на 2 части — псевдо-постоянная и псевдо-оперативная. 1-ая — типа жёсткого диска, на ней находиться исполняемый код, эта область самая большая. 2-ая — типа оперативной памяти, там находятся динамические данные, она маленькая. Псевдо, поому что реально всё лежало на одной флэшке. Как и любой современный компилятор, тот компилятор, который использовал я, старался все постоянные данные вычислить при компиляции и разместить внутри исполняемого кода, чтобы они оказались в 1-ой области памяти и не занимали место во 2-ой. На той платформе примерно вот такой код:
const long val = 10;
...
(long)val = 15;
приводил к аппаратной ошибке: Запись в область памяти, недоступную для динамического изменения. Из анализа сообщения было понятно, что идёт попытка записи в 1-ую область памяти, что недопустимо. То ли это был прикол компилятора (который не прочухивал изменение константы с применением C-style преобразования, и размещал её в коде не смотря ни на что), то ли платформы, то ли симбиоз компилятора и платформы, сказать трудно. Замена (long) на const_cast<long> решило проблему и код в такой виде:
const long val = 10;
...
const_cast<long>(val) = 15;
увидел свет...
Мораль, НИКОГДА не снимайте константность с переменных, а если это вам всё таки нужно НЕ ИСПОЛЬЗУЙТЕ для этих целей C-style — снимайте константность ТОЛЬКО с помощью const_cast.
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Re[2]: (float) и static_cast(float): в чем разница?
Здравствуйте, Mr. None, Вы писали:
MN>Замена (long) на const_cast<long> решило проблему и код в такой виде: MN>
MN>const long val = 10;
MN>...
MN>const_cast<long>(val) = 15;
MN>
MN>увидел свет...
MN>Мораль, НИКОГДА не снимайте константность с переменных, а если это вам всё таки нужно НЕ ИСПОЛЬЗУЙТЕ для этих целей C-style — снимайте константность ТОЛЬКО с помощью const_cast.
Здравствуйте, remark, Вы писали:
MN>>Замена (long) на const_cast<long> решило проблему и код в такой виде: MN>>
MN>>const long val = 10;
MN>>...
MN>>const_cast<long>(val) = 15;
MN>>
MN>>увидел свет...
MN>>Мораль, НИКОГДА не снимайте константность с переменных, а если это вам всё таки нужно НЕ ИСПОЛЬЗУЙТЕ для этих целей C-style — снимайте константность ТОЛЬКО с помощью const_cast.
R>IMHO, это тоже UB, и тоже не должно работать...
+1, если val размещена в памяти только для чтения, тут ничто не поможет.
Кстати, тот код даже ill-formed, надо было const_cast<long &>. А вообще const_cast можно использовать только для того, чтобы получить из константной ссылки (указателя), указывающей на неконстантный объект, неконстантную ссылку (указатель).
X x;
X const& y = x;
X& z = const_cast<X &>(y); // well-formed, well-defined
Что еще нужно помнить про const_cast: он работает не только с квалификаторои const, но и с volatile, и может незаметно сбросить последний, отчего и без того трудноуловимые многопоточные баги станут еще менее приятны.
До последнего не верил в пирамиду Лебедева.
Re[2]: (float) и static_cast(float): в чем разница?
Здравствуйте, Programador, Вы писали:
P>Здравствуйте, Mr. None, Вы писали: MN>>
MN>>const long val = 10;
MN>>...
MN>>(long)val = 15;
MN>>
MN>>
MN>>const long val = 10;
MN>>...
MN>>const_cast<long>(val) = 15;
MN>>
P>и то и другое не левое. Это какойто сильно неправильный компилятор
Писал по мотивам, подробностей уже всех не помню, так как было лет 5 назад. Но смысл именно такой, const_cast лечило проблему. А компилятор кстати был Code Warrior...
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Re[3]: (float) и static_cast(float): в чем разница?
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Mr. None, Вы писали:
MN>>Замена (long) на const_cast<long> решило проблему и код в такой виде: MN>>
MN>>const long val = 10;
MN>>...
MN>>const_cast<long>(val) = 15;
MN>>
MN>>увидел свет...
MN>>Мораль, НИКОГДА не снимайте константность с переменных, а если это вам всё таки нужно НЕ ИСПОЛЬЗУЙТЕ для этих целей C-style — снимайте константность ТОЛЬКО с помощью const_cast.
R>IMHO, это тоже UB, и тоже не должно работать...
R>
Здравствуйте, Mr. None, Вы писали:
MN>Писал по мотивам, подробностей уже всех не помню, так как было лет 5 назад. Но смысл именно такой, const_cast лечило проблему. А компилятор кстати был Code Warrior...
Дело в следующем — флэш конечно допускает запись (возможно блочную), допускаю что Code Warrior какимто образом это делает, но эта ситуация уже за пределами стандарта. А вообще для записи нужно приводить к ссылке (int&)
Re[5]: (float) и static_cast(float): в чем разница?
> MN>Писал по мотивам, подробностей уже всех не помню, так как было лет 5 назад. Но смысл именно такой, const_cast лечило проблему. А компилятор кстати был Code Warrior... > Дело в следующем — флэш конечно допускает запись (возможно блочную), допускаю что Code Warrior какимто образом это делает, но эта ситуация уже за пределами стандарта. А вообще для записи нужно приводить к ссылке (int&) >
По стандарту, как тут уже говорил remark, тут UB в обоих случаях. Соответственно, Code Warrior в своем праве — че хочет, то и делает.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[6]: (float) и static_cast(float): в чем разница?
Здравствуйте, Sergey, Вы писали:
>> MN>Писал по мотивам, подробностей уже всех не помню, так как было лет 5 назад. Но смысл именно такой, const_cast лечило проблему. А компилятор кстати был Code Warrior... >> Дело в следующем — флэш конечно допускает запись (возможно блочную), допускаю что Code Warrior какимто образом это делает, но эта ситуация уже за пределами стандарта. А вообще для записи нужно приводить к ссылке (int&) >>
S>По стандарту, как тут уже говорил remark, тут UB в обоих случаях. Соответственно, Code Warrior в своем праве — че хочет, то и делает.
Да нетже, здесь UB по одной причине + ill-formed по другой, еще Roman Odaisky это отметил (не видел его поста когда писал)
Здравствуйте, Pavor, Вы писали:
P>(float) и static_cast(float): в чем разница? P>Собственно вот такой вопрос и есть..
порылся в стандарте,
5.2.9 Static cast [expr.static.cast]
1 The result of the expression static_cast<T>(v) is the result of converting the expression v to type T.
If T is a reference type, the result is an lvalue; otherwise, the result is an rvalue. Types shall not be defined in a static_cast. The static_cast operator shall not cast away constness (5.2.11).
попробовал разные компиляторы, результат для структуры и целого отличается. Собственно зачем писать (T) когда нужно (&T).
Но вот это меня сильно озадачило
struct St {int v;St(int);};
void f()
{ typedef int T;
//typedef St T;
T a=1;
static_cast<T>(a)=__LINE__; //expression must be a modifiable lvalue
(T)a=__LINE__; //expression must be a modifiable lvalue
T(a)=__LINE__; // "a" has already been declared in the current scope
{
T(c)=__LINE__;
T(b)=__LINE__;
c=b;
c=T(b);
}
}
void f()
{ int a;
int(a);//error: "a" has already been declared in the current scopeint((int)a);// warning: expression has no effectint(0);// warningint;//warning: ignored on left of 'int' when no variable is declared
}
Re[2]: (float) и static_cast(float): в чем разница?
От:
Аноним
Дата:
14.08.07 13:44
Оценка:
Здравствуйте, Programador, Вы писали:
P>так что — никто не знает?
P>
P>void f()
P>{ int a;
P> int(a);//error: "a" has already been declared in the current scope
P> int((int)a);// warning: expression has no effect
P> int(0);// warning
P> int;//warning: ignored on left of 'int' when no variable is declared
P>}
P>
И? Нужно перевести текст ошибок/предупреждений на русский?
Re[2]: (float) и static_cast(float): в чем разница?
Здравствуйте, BitField, Вы писали:
BF>Здравствуйте, Programador, Вы писали:
BF>
P>>> int a; // обьявление переменной a..
P>>> int(a); // еще обно обьявление переменной а
BF>
С чегобы это еще обно обьявление?
Это вызов конструктора и создание безымянной переменной, чем это отличается от следующей строчки?
Еслиб int a; была в внешнем контексте то так и скомпилировалосьбы.
Вот захотелось позвать конструктор, а обьект не нужен — ситуация крайне двухсмысленная
Re[3]: (float) и static_cast(float): в чем разница?
Здравствуйте, Аноним, Вы писали:
А>И? Нужно перевести текст ошибок/предупреждений на русский?
В стандарте гдето сказано что скобки можно добавлять и убирать где попало?
Re[2]: (float) и static_cast(float): в чем разница?
P> T a=1;
P> T(a)=__LINE__; // "a" has already been declared in the current scope[/b]
А что не так? Всё что может быть декларацией -- ей и является.
T (a); -- это декларация a типа T с лишними скобками, что собственно не мешает.
T(a) = __LINE__; то же, но с инициализатором
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: (float) и static_cast(float): в чем разница?
P>С чегобы это еще обно обьявление? P>Это вызов конструктора и создание безымянной переменной, чем это отличается от следующей строчки? P>Еслиб int a; была в внешнем контексте то так и скомпилировалосьбы. P>Вот захотелось позвать конструктор, а обьект не нужен — ситуация крайне двухсмысленная
Есть правило -- всё, что может быть декларацией, ей и является.
Вот оно самое и есть.
Если хлчешь безымянный объект породить, сделай так, чтобы не было декларацией. Скажем так:
1, int( a );
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: (float) и static_cast(float): в чем разница?
Здравствуйте, Programador, Вы писали:
E>>Есть правило -- всё, что может быть декларацией, ей и является. P>Похоже что все компиляторы себя так ведут
Да это где-то в стандарте в "основных понятиях" записано. Просто нет сейчас, чтобы искать.
P>Но засада класная
А где "спасибо"?
Лично мне больше нравится другая версия той же засады:
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: (float) и static_cast(float): в чем разница?
Здравствуйте, Erop, Вы писали:
P>>Но засада класная E>А где "спасибо"?
спасибо
Еще большое писателям стандарта
E>Если хлчешь безымянный объект породить, сделай так, чтобы не было декларацией. Скажем так: E>
1, int( a );
кстати на (int a); ругается поэтому (ххх(аа)); обьявлением не является. Более явный метод позвать конструктор. Хотя после этого уже во всем сомневаешся